xref: /petsc/src/mat/impls/aij/mpi/mpiaij.c (revision 73a71a0f875e342bef2af9dbfc05b9368f8a1bc4)
18a729477SBarry Smith 
2c6db04a5SJed Brown #include <../src/mat/impls/aij/mpi/mpiaij.h>   /*I "petscmat.h" I*/
3c6db04a5SJed Brown #include <petscblaslapack.h>
48a729477SBarry Smith 
501bebe75SBarry Smith /*MC
601bebe75SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
701bebe75SBarry Smith 
801bebe75SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
901bebe75SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
1001bebe75SBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation is supported
1101bebe75SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
1201bebe75SBarry Smith   the above preallocation routines for simplicity.
1301bebe75SBarry Smith 
1401bebe75SBarry Smith    Options Database Keys:
1501bebe75SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
1601bebe75SBarry Smith 
179ae82921SPaul Mullowney   Developer Notes: Subclasses include MATAIJCUSP, MATAIJCUSPARSE, MATAIJPERM, MATAIJCRL, and also automatically switches over to use inodes when
1801bebe75SBarry Smith    enough exist.
1901bebe75SBarry Smith 
2001bebe75SBarry Smith   Level: beginner
2101bebe75SBarry Smith 
2269b1f4b7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
2301bebe75SBarry Smith M*/
2401bebe75SBarry Smith 
2501bebe75SBarry Smith /*MC
2601bebe75SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
2701bebe75SBarry Smith 
2801bebe75SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
2901bebe75SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
3001bebe75SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
3101bebe75SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
3201bebe75SBarry Smith   the above preallocation routines for simplicity.
3301bebe75SBarry Smith 
3401bebe75SBarry Smith    Options Database Keys:
3501bebe75SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
3601bebe75SBarry Smith 
3701bebe75SBarry Smith   Level: beginner
3801bebe75SBarry Smith 
3901bebe75SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4001bebe75SBarry Smith M*/
4101bebe75SBarry Smith 
42dd6ea824SBarry Smith #undef __FUNCT__
43f2c98031SJed Brown #define __FUNCT__ "MatFindNonzeroRows_MPIAIJ"
44f2c98031SJed Brown PetscErrorCode MatFindNonzeroRows_MPIAIJ(Mat M,IS *keptrows)
4527d4218bSShri Abhyankar {
4627d4218bSShri Abhyankar   PetscErrorCode  ierr;
4727d4218bSShri Abhyankar   Mat_MPIAIJ      *mat = (Mat_MPIAIJ*)M->data;
4827d4218bSShri Abhyankar   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)mat->A->data;
4927d4218bSShri Abhyankar   Mat_SeqAIJ      *b = (Mat_SeqAIJ*)mat->B->data;
5027d4218bSShri Abhyankar   const PetscInt  *ia,*ib;
5127d4218bSShri Abhyankar   const MatScalar *aa,*bb;
5227d4218bSShri Abhyankar   PetscInt        na,nb,i,j,*rows,cnt=0,n0rows;
5327d4218bSShri Abhyankar   PetscInt        m = M->rmap->n,rstart = M->rmap->rstart;
5427d4218bSShri Abhyankar 
5527d4218bSShri Abhyankar   PetscFunctionBegin;
5627d4218bSShri Abhyankar   *keptrows = 0;
5727d4218bSShri Abhyankar   ia = a->i;
5827d4218bSShri Abhyankar   ib = b->i;
5927d4218bSShri Abhyankar   for (i=0; i<m; i++) {
6027d4218bSShri Abhyankar     na = ia[i+1] - ia[i];
6127d4218bSShri Abhyankar     nb = ib[i+1] - ib[i];
6227d4218bSShri Abhyankar     if (!na && !nb) {
6327d4218bSShri Abhyankar       cnt++;
6427d4218bSShri Abhyankar       goto ok1;
6527d4218bSShri Abhyankar     }
6627d4218bSShri Abhyankar     aa = a->a + ia[i];
6727d4218bSShri Abhyankar     for (j=0; j<na; j++) {
6827d4218bSShri Abhyankar       if (aa[j] != 0.0) goto ok1;
6927d4218bSShri Abhyankar     }
7027d4218bSShri Abhyankar     bb = b->a + ib[i];
7127d4218bSShri Abhyankar     for (j=0; j <nb; j++) {
7227d4218bSShri Abhyankar       if (bb[j] != 0.0) goto ok1;
7327d4218bSShri Abhyankar     }
7427d4218bSShri Abhyankar     cnt++;
7527d4218bSShri Abhyankar     ok1:;
7627d4218bSShri Abhyankar   }
7727d4218bSShri Abhyankar   ierr = MPI_Allreduce(&cnt,&n0rows,1,MPIU_INT,MPI_SUM,((PetscObject)M)->comm);CHKERRQ(ierr);
7827d4218bSShri Abhyankar   if (!n0rows) PetscFunctionReturn(0);
7927d4218bSShri Abhyankar   ierr = PetscMalloc((M->rmap->n-cnt)*sizeof(PetscInt),&rows);CHKERRQ(ierr);
8027d4218bSShri Abhyankar   cnt = 0;
8127d4218bSShri Abhyankar   for (i=0; i<m; i++) {
8227d4218bSShri Abhyankar     na = ia[i+1] - ia[i];
8327d4218bSShri Abhyankar     nb = ib[i+1] - ib[i];
8427d4218bSShri Abhyankar     if (!na && !nb) continue;
8527d4218bSShri Abhyankar     aa = a->a + ia[i];
8627d4218bSShri Abhyankar     for(j=0; j<na;j++) {
8727d4218bSShri Abhyankar       if (aa[j] != 0.0) {
8827d4218bSShri Abhyankar         rows[cnt++] = rstart + i;
8927d4218bSShri Abhyankar         goto ok2;
9027d4218bSShri Abhyankar       }
9127d4218bSShri Abhyankar     }
9227d4218bSShri Abhyankar     bb = b->a + ib[i];
9327d4218bSShri Abhyankar     for (j=0; j<nb; j++) {
9427d4218bSShri Abhyankar       if (bb[j] != 0.0) {
9527d4218bSShri Abhyankar         rows[cnt++] = rstart + i;
9627d4218bSShri Abhyankar         goto ok2;
9727d4218bSShri Abhyankar       }
9827d4218bSShri Abhyankar     }
9927d4218bSShri Abhyankar     ok2:;
10027d4218bSShri Abhyankar   }
10177c8aea5SJed Brown   ierr = ISCreateGeneral(((PetscObject)M)->comm,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr);
10227d4218bSShri Abhyankar   PetscFunctionReturn(0);
10327d4218bSShri Abhyankar }
10427d4218bSShri Abhyankar 
10527d4218bSShri Abhyankar #undef __FUNCT__
106f1f41ecbSJed Brown #define __FUNCT__ "MatFindZeroDiagonals_MPIAIJ"
107f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_MPIAIJ(Mat M,IS *zrows)
108f1f41ecbSJed Brown {
109f1f41ecbSJed Brown   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)M->data;
110f1f41ecbSJed Brown   PetscErrorCode ierr;
111f1f41ecbSJed Brown   PetscInt       i,rstart,nrows,*rows;
112f1f41ecbSJed Brown 
113f1f41ecbSJed Brown   PetscFunctionBegin;
114f1f41ecbSJed Brown   *zrows = PETSC_NULL;
115f1f41ecbSJed Brown   ierr = MatFindZeroDiagonals_SeqAIJ_Private(aij->A,&nrows,&rows);CHKERRQ(ierr);
116f1f41ecbSJed Brown   ierr = MatGetOwnershipRange(M,&rstart,PETSC_NULL);CHKERRQ(ierr);
117f1f41ecbSJed Brown   for (i=0; i<nrows; i++) rows[i] += rstart;
118f1f41ecbSJed Brown   ierr = ISCreateGeneral(((PetscObject)M)->comm,nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr);
119f1f41ecbSJed Brown   PetscFunctionReturn(0);
120f1f41ecbSJed Brown }
121f1f41ecbSJed Brown 
122f1f41ecbSJed Brown #undef __FUNCT__
1230716a85fSBarry Smith #define __FUNCT__ "MatGetColumnNorms_MPIAIJ"
1240716a85fSBarry Smith PetscErrorCode MatGetColumnNorms_MPIAIJ(Mat A,NormType type,PetscReal *norms)
1250716a85fSBarry Smith {
1260716a85fSBarry Smith   PetscErrorCode ierr;
1270716a85fSBarry Smith   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)A->data;
1280716a85fSBarry Smith   PetscInt       i,n,*garray = aij->garray;
1290716a85fSBarry Smith   Mat_SeqAIJ     *a_aij = (Mat_SeqAIJ*) aij->A->data;
1300716a85fSBarry Smith   Mat_SeqAIJ     *b_aij = (Mat_SeqAIJ*) aij->B->data;
1310716a85fSBarry Smith   PetscReal      *work;
1320716a85fSBarry Smith 
1330716a85fSBarry Smith   PetscFunctionBegin;
1340716a85fSBarry Smith   ierr = MatGetSize(A,PETSC_NULL,&n);CHKERRQ(ierr);
1350716a85fSBarry Smith   ierr = PetscMalloc(n*sizeof(PetscReal),&work);CHKERRQ(ierr);
1360716a85fSBarry Smith   ierr = PetscMemzero(work,n*sizeof(PetscReal));CHKERRQ(ierr);
1370716a85fSBarry Smith   if (type == NORM_2) {
1380716a85fSBarry Smith     for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) {
1390716a85fSBarry Smith       work[A->cmap->rstart + a_aij->j[i]] += PetscAbsScalar(a_aij->a[i]*a_aij->a[i]);
1400716a85fSBarry Smith     }
1410716a85fSBarry Smith     for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) {
1420716a85fSBarry Smith       work[garray[b_aij->j[i]]] += PetscAbsScalar(b_aij->a[i]*b_aij->a[i]);
1430716a85fSBarry Smith     }
1440716a85fSBarry Smith   } else if (type == NORM_1) {
1450716a85fSBarry Smith     for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) {
1460716a85fSBarry Smith       work[A->cmap->rstart + a_aij->j[i]] += PetscAbsScalar(a_aij->a[i]);
1470716a85fSBarry Smith     }
1480716a85fSBarry Smith     for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) {
1490716a85fSBarry Smith       work[garray[b_aij->j[i]]] += PetscAbsScalar(b_aij->a[i]);
1500716a85fSBarry Smith     }
1510716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
1520716a85fSBarry Smith     for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) {
1530716a85fSBarry Smith       work[A->cmap->rstart + a_aij->j[i]] = PetscMax(PetscAbsScalar(a_aij->a[i]), work[A->cmap->rstart + a_aij->j[i]]);
1540716a85fSBarry Smith     }
1550716a85fSBarry Smith     for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) {
1560716a85fSBarry Smith       work[garray[b_aij->j[i]]] = PetscMax(PetscAbsScalar(b_aij->a[i]),work[garray[b_aij->j[i]]]);
1570716a85fSBarry Smith     }
1580716a85fSBarry Smith 
1590716a85fSBarry Smith   } else SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONG,"Unknown NormType");
1600716a85fSBarry Smith   if (type == NORM_INFINITY) {
1610716a85fSBarry Smith     ierr = MPI_Allreduce(work,norms,n,MPIU_REAL,MPIU_MAX,A->hdr.comm);CHKERRQ(ierr);
1620716a85fSBarry Smith   } else {
1630716a85fSBarry Smith     ierr = MPI_Allreduce(work,norms,n,MPIU_REAL,MPIU_SUM,A->hdr.comm);CHKERRQ(ierr);
1640716a85fSBarry Smith   }
1650716a85fSBarry Smith   ierr = PetscFree(work);CHKERRQ(ierr);
1660716a85fSBarry Smith   if (type == NORM_2) {
1678f1a2a5eSBarry Smith     for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
1680716a85fSBarry Smith   }
1690716a85fSBarry Smith   PetscFunctionReturn(0);
1700716a85fSBarry Smith }
1710716a85fSBarry Smith 
1720716a85fSBarry Smith #undef __FUNCT__
173dd6ea824SBarry Smith #define __FUNCT__ "MatDistribute_MPIAIJ"
174dd6ea824SBarry Smith /*
175dd6ea824SBarry Smith     Distributes a SeqAIJ matrix across a set of processes. Code stolen from
176dd6ea824SBarry Smith     MatLoad_MPIAIJ(). Horrible lack of reuse. Should be a routine for each matrix type.
177dd6ea824SBarry Smith 
178dd6ea824SBarry Smith     Only for square matrices
179dd6ea824SBarry Smith */
180dd6ea824SBarry Smith PetscErrorCode MatDistribute_MPIAIJ(MPI_Comm comm,Mat gmat,PetscInt m,MatReuse reuse,Mat *inmat)
181dd6ea824SBarry Smith {
182dd6ea824SBarry Smith   PetscMPIInt    rank,size;
183dd6ea824SBarry Smith   PetscInt       *rowners,*dlens,*olens,i,rstart,rend,j,jj,nz,*gmataj,cnt,row,*ld;
184dd6ea824SBarry Smith   PetscErrorCode ierr;
185dd6ea824SBarry Smith   Mat            mat;
186dd6ea824SBarry Smith   Mat_SeqAIJ     *gmata;
187dd6ea824SBarry Smith   PetscMPIInt    tag;
188dd6ea824SBarry Smith   MPI_Status     status;
189ace3abfcSBarry Smith   PetscBool      aij;
190dd6ea824SBarry Smith   MatScalar      *gmataa,*ao,*ad,*gmataarestore=0;
191dd6ea824SBarry Smith 
192dd6ea824SBarry Smith   PetscFunctionBegin;
193dd6ea824SBarry Smith   CHKMEMQ;
194dd6ea824SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
195dd6ea824SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
196dd6ea824SBarry Smith   if (!rank) {
197251f4c67SDmitry Karpeev     ierr = PetscObjectTypeCompare((PetscObject)gmat,MATSEQAIJ,&aij);CHKERRQ(ierr);
19865e19b50SBarry Smith     if (!aij) SETERRQ1(((PetscObject)gmat)->comm,PETSC_ERR_SUP,"Currently no support for input matrix of type %s\n",((PetscObject)gmat)->type_name);
199dd6ea824SBarry Smith   }
200dd6ea824SBarry Smith   if (reuse == MAT_INITIAL_MATRIX) {
201dd6ea824SBarry Smith     ierr = MatCreate(comm,&mat);CHKERRQ(ierr);
202dd6ea824SBarry Smith     ierr = MatSetSizes(mat,m,m,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
203a2f3521dSMark F. Adams     ierr = MatSetBlockSizes(mat,gmat->rmap->bs,gmat->cmap->bs);CHKERRQ(ierr);
204dd6ea824SBarry Smith     ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
205dd6ea824SBarry Smith     ierr = PetscMalloc((size+1)*sizeof(PetscInt),&rowners);CHKERRQ(ierr);
206dd6ea824SBarry Smith     ierr = PetscMalloc2(m,PetscInt,&dlens,m,PetscInt,&olens);CHKERRQ(ierr);
207dd6ea824SBarry Smith     ierr = MPI_Allgather(&m,1,MPIU_INT,rowners+1,1,MPIU_INT,comm);CHKERRQ(ierr);
208dd6ea824SBarry Smith     rowners[0] = 0;
209dd6ea824SBarry Smith     for (i=2; i<=size; i++) {
210dd6ea824SBarry Smith       rowners[i] += rowners[i-1];
211dd6ea824SBarry Smith     }
212dd6ea824SBarry Smith     rstart = rowners[rank];
213dd6ea824SBarry Smith     rend   = rowners[rank+1];
214dd6ea824SBarry Smith     ierr   = PetscObjectGetNewTag((PetscObject)mat,&tag);CHKERRQ(ierr);
215dd6ea824SBarry Smith     if (!rank) {
216dd6ea824SBarry Smith       gmata = (Mat_SeqAIJ*) gmat->data;
217dd6ea824SBarry Smith       /* send row lengths to all processors */
218dd6ea824SBarry Smith       for (i=0; i<m; i++) dlens[i] = gmata->ilen[i];
219dd6ea824SBarry Smith       for (i=1; i<size; i++) {
220dd6ea824SBarry Smith 	ierr = MPI_Send(gmata->ilen + rowners[i],rowners[i+1]-rowners[i],MPIU_INT,i,tag,comm);CHKERRQ(ierr);
221dd6ea824SBarry Smith       }
222dd6ea824SBarry Smith       /* determine number diagonal and off-diagonal counts */
223dd6ea824SBarry Smith       ierr = PetscMemzero(olens,m*sizeof(PetscInt));CHKERRQ(ierr);
224dd6ea824SBarry Smith       ierr = PetscMalloc(m*sizeof(PetscInt),&ld);CHKERRQ(ierr);
225dd6ea824SBarry Smith       ierr = PetscMemzero(ld,m*sizeof(PetscInt));CHKERRQ(ierr);
226dd6ea824SBarry Smith       jj = 0;
227dd6ea824SBarry Smith       for (i=0; i<m; i++) {
228dd6ea824SBarry Smith 	for (j=0; j<dlens[i]; j++) {
229dd6ea824SBarry Smith           if (gmata->j[jj] < rstart) ld[i]++;
230dd6ea824SBarry Smith 	  if (gmata->j[jj] < rstart || gmata->j[jj] >= rend) olens[i]++;
231dd6ea824SBarry Smith 	  jj++;
232dd6ea824SBarry Smith 	}
233dd6ea824SBarry Smith       }
234dd6ea824SBarry Smith       /* send column indices to other processes */
235dd6ea824SBarry Smith       for (i=1; i<size; i++) {
236dd6ea824SBarry Smith 	nz   = gmata->i[rowners[i+1]]-gmata->i[rowners[i]];
237dd6ea824SBarry Smith 	ierr = MPI_Send(&nz,1,MPIU_INT,i,tag,comm);CHKERRQ(ierr);
238dd6ea824SBarry Smith 	ierr = MPI_Send(gmata->j + gmata->i[rowners[i]],nz,MPIU_INT,i,tag,comm);CHKERRQ(ierr);
239dd6ea824SBarry Smith       }
240dd6ea824SBarry Smith 
241dd6ea824SBarry Smith       /* send numerical values to other processes */
242dd6ea824SBarry Smith       for (i=1; i<size; i++) {
243dd6ea824SBarry Smith         nz   = gmata->i[rowners[i+1]]-gmata->i[rowners[i]];
244dd6ea824SBarry Smith         ierr = MPI_Send(gmata->a + gmata->i[rowners[i]],nz,MPIU_SCALAR,i,tag,comm);CHKERRQ(ierr);
245dd6ea824SBarry Smith       }
246dd6ea824SBarry Smith       gmataa = gmata->a;
247dd6ea824SBarry Smith       gmataj = gmata->j;
248dd6ea824SBarry Smith 
249dd6ea824SBarry Smith     } else {
250dd6ea824SBarry Smith       /* receive row lengths */
251dd6ea824SBarry Smith       ierr = MPI_Recv(dlens,m,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr);
252dd6ea824SBarry Smith       /* receive column indices */
253dd6ea824SBarry Smith       ierr = MPI_Recv(&nz,1,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr);
254dd6ea824SBarry Smith       ierr = PetscMalloc2(nz,PetscScalar,&gmataa,nz,PetscInt,&gmataj);CHKERRQ(ierr);
255dd6ea824SBarry Smith       ierr = MPI_Recv(gmataj,nz,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr);
256dd6ea824SBarry Smith       /* determine number diagonal and off-diagonal counts */
257dd6ea824SBarry Smith       ierr = PetscMemzero(olens,m*sizeof(PetscInt));CHKERRQ(ierr);
258dd6ea824SBarry Smith       ierr = PetscMalloc(m*sizeof(PetscInt),&ld);CHKERRQ(ierr);
259dd6ea824SBarry Smith       ierr = PetscMemzero(ld,m*sizeof(PetscInt));CHKERRQ(ierr);
260dd6ea824SBarry Smith       jj = 0;
261dd6ea824SBarry Smith       for (i=0; i<m; i++) {
262dd6ea824SBarry Smith 	for (j=0; j<dlens[i]; j++) {
263dd6ea824SBarry Smith           if (gmataj[jj] < rstart) ld[i]++;
264dd6ea824SBarry Smith 	  if (gmataj[jj] < rstart || gmataj[jj] >= rend) olens[i]++;
265dd6ea824SBarry Smith 	  jj++;
266dd6ea824SBarry Smith 	}
267dd6ea824SBarry Smith       }
268dd6ea824SBarry Smith       /* receive numerical values */
269dd6ea824SBarry Smith       ierr = PetscMemzero(gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr);
270dd6ea824SBarry Smith       ierr = MPI_Recv(gmataa,nz,MPIU_SCALAR,0,tag,comm,&status);CHKERRQ(ierr);
271dd6ea824SBarry Smith     }
272dd6ea824SBarry Smith     /* set preallocation */
273dd6ea824SBarry Smith     for (i=0; i<m; i++) {
274dd6ea824SBarry Smith       dlens[i] -= olens[i];
275dd6ea824SBarry Smith     }
276dd6ea824SBarry Smith     ierr = MatSeqAIJSetPreallocation(mat,0,dlens);CHKERRQ(ierr);
277dd6ea824SBarry Smith     ierr = MatMPIAIJSetPreallocation(mat,0,dlens,0,olens);CHKERRQ(ierr);
278dd6ea824SBarry Smith 
279dd6ea824SBarry Smith     for (i=0; i<m; i++) {
280dd6ea824SBarry Smith       dlens[i] += olens[i];
281dd6ea824SBarry Smith     }
282dd6ea824SBarry Smith     cnt  = 0;
283dd6ea824SBarry Smith     for (i=0; i<m; i++) {
284dd6ea824SBarry Smith       row  = rstart + i;
285dd6ea824SBarry Smith       ierr = MatSetValues(mat,1,&row,dlens[i],gmataj+cnt,gmataa+cnt,INSERT_VALUES);CHKERRQ(ierr);
286dd6ea824SBarry Smith       cnt += dlens[i];
287dd6ea824SBarry Smith     }
288dd6ea824SBarry Smith     if (rank) {
289dd6ea824SBarry Smith       ierr = PetscFree2(gmataa,gmataj);CHKERRQ(ierr);
290dd6ea824SBarry Smith     }
291dd6ea824SBarry Smith     ierr = PetscFree2(dlens,olens);CHKERRQ(ierr);
292dd6ea824SBarry Smith     ierr = PetscFree(rowners);CHKERRQ(ierr);
293dd6ea824SBarry Smith     ((Mat_MPIAIJ*)(mat->data))->ld = ld;
294dd6ea824SBarry Smith     *inmat = mat;
295dd6ea824SBarry Smith   } else {   /* column indices are already set; only need to move over numerical values from process 0 */
296dd6ea824SBarry Smith     Mat_SeqAIJ *Ad = (Mat_SeqAIJ*)((Mat_MPIAIJ*)((*inmat)->data))->A->data;
297dd6ea824SBarry Smith     Mat_SeqAIJ *Ao = (Mat_SeqAIJ*)((Mat_MPIAIJ*)((*inmat)->data))->B->data;
298dd6ea824SBarry Smith     mat   = *inmat;
299dd6ea824SBarry Smith     ierr  = PetscObjectGetNewTag((PetscObject)mat,&tag);CHKERRQ(ierr);
300dd6ea824SBarry Smith     if (!rank) {
301dd6ea824SBarry Smith       /* send numerical values to other processes */
302dd6ea824SBarry Smith       gmata = (Mat_SeqAIJ*) gmat->data;
303dd6ea824SBarry Smith       ierr   = MatGetOwnershipRanges(mat,(const PetscInt**)&rowners);CHKERRQ(ierr);
304dd6ea824SBarry Smith       gmataa = gmata->a;
305dd6ea824SBarry Smith       for (i=1; i<size; i++) {
306dd6ea824SBarry Smith         nz   = gmata->i[rowners[i+1]]-gmata->i[rowners[i]];
307dd6ea824SBarry Smith         ierr = MPI_Send(gmataa + gmata->i[rowners[i]],nz,MPIU_SCALAR,i,tag,comm);CHKERRQ(ierr);
308dd6ea824SBarry Smith       }
309dd6ea824SBarry Smith       nz   = gmata->i[rowners[1]]-gmata->i[rowners[0]];
310dd6ea824SBarry Smith     } else {
311dd6ea824SBarry Smith       /* receive numerical values from process 0*/
312dd6ea824SBarry Smith       nz   = Ad->nz + Ao->nz;
313dd6ea824SBarry Smith       ierr = PetscMalloc(nz*sizeof(PetscScalar),&gmataa);CHKERRQ(ierr); gmataarestore = gmataa;
314dd6ea824SBarry Smith       ierr = MPI_Recv(gmataa,nz,MPIU_SCALAR,0,tag,comm,&status);CHKERRQ(ierr);
315dd6ea824SBarry Smith     }
316dd6ea824SBarry Smith     /* transfer numerical values into the diagonal A and off diagonal B parts of mat */
317dd6ea824SBarry Smith     ld = ((Mat_MPIAIJ*)(mat->data))->ld;
318dd6ea824SBarry Smith     ad = Ad->a;
319dd6ea824SBarry Smith     ao = Ao->a;
320d0f46423SBarry Smith     if (mat->rmap->n) {
321dd6ea824SBarry Smith       i  = 0;
322dd6ea824SBarry Smith       nz = ld[i];                                   ierr = PetscMemcpy(ao,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ao += nz; gmataa += nz;
323dd6ea824SBarry Smith       nz = Ad->i[i+1] - Ad->i[i];                   ierr = PetscMemcpy(ad,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ad += nz; gmataa += nz;
324dd6ea824SBarry Smith     }
325d0f46423SBarry Smith     for (i=1; i<mat->rmap->n; i++) {
326dd6ea824SBarry Smith       nz = Ao->i[i] - Ao->i[i-1] - ld[i-1] + ld[i]; ierr = PetscMemcpy(ao,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ao += nz; gmataa += nz;
327dd6ea824SBarry Smith       nz = Ad->i[i+1] - Ad->i[i];                   ierr = PetscMemcpy(ad,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ad += nz; gmataa += nz;
328dd6ea824SBarry Smith     }
329dd6ea824SBarry Smith     i--;
330d0f46423SBarry Smith     if (mat->rmap->n) {
331dd6ea824SBarry Smith       nz = Ao->i[i+1] - Ao->i[i] - ld[i];           ierr = PetscMemcpy(ao,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ao += nz; gmataa += nz;
332dd6ea824SBarry Smith     }
333dd6ea824SBarry Smith     if (rank) {
334dd6ea824SBarry Smith       ierr = PetscFree(gmataarestore);CHKERRQ(ierr);
335dd6ea824SBarry Smith     }
336dd6ea824SBarry Smith   }
337dd6ea824SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
338dd6ea824SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
339dd6ea824SBarry Smith   CHKMEMQ;
340dd6ea824SBarry Smith   PetscFunctionReturn(0);
341dd6ea824SBarry Smith }
342dd6ea824SBarry Smith 
3430f5bd95cSBarry Smith /*
3440f5bd95cSBarry Smith   Local utility routine that creates a mapping from the global column
3459e25ed09SBarry Smith number to the local number in the off-diagonal part of the local
3460f5bd95cSBarry Smith storage of the matrix.  When PETSC_USE_CTABLE is used this is scalable at
3470f5bd95cSBarry Smith a slightly higher hash table cost; without it it is not scalable (each processor
3480f5bd95cSBarry Smith has an order N integer array but is fast to acess.
3499e25ed09SBarry Smith */
3504a2ae208SSatish Balay #undef __FUNCT__
351ab9863d7SBarry Smith #define __FUNCT__ "MatCreateColmap_MPIAIJ_Private"
352ab9863d7SBarry Smith PetscErrorCode MatCreateColmap_MPIAIJ_Private(Mat mat)
3539e25ed09SBarry Smith {
35444a69424SLois Curfman McInnes   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)mat->data;
3556849ba73SBarry Smith   PetscErrorCode ierr;
356d0f46423SBarry Smith   PetscInt       n = aij->B->cmap->n,i;
357dbb450caSBarry Smith 
3583a40ed3dSBarry Smith   PetscFunctionBegin;
3595e1f6667SBarry Smith   if (!aij->garray) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"MPIAIJ Matrix was assembled but is missing garray");
360aa482453SBarry Smith #if defined (PETSC_USE_CTABLE)
361e23dfa41SBarry Smith   ierr = PetscTableCreate(n,mat->cmap->N+1,&aij->colmap);CHKERRQ(ierr);
362b1fc9764SSatish Balay   for (i=0; i<n; i++){
3633861aac3SJed Brown     ierr = PetscTableAdd(aij->colmap,aij->garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
364b1fc9764SSatish Balay   }
365b1fc9764SSatish Balay #else
366d0f46423SBarry Smith   ierr = PetscMalloc((mat->cmap->N+1)*sizeof(PetscInt),&aij->colmap);CHKERRQ(ierr);
367d0f46423SBarry Smith   ierr = PetscLogObjectMemory(mat,mat->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
368d0f46423SBarry Smith   ierr = PetscMemzero(aij->colmap,mat->cmap->N*sizeof(PetscInt));CHKERRQ(ierr);
369905e6a2fSBarry Smith   for (i=0; i<n; i++) aij->colmap[aij->garray[i]] = i+1;
370b1fc9764SSatish Balay #endif
3713a40ed3dSBarry Smith   PetscFunctionReturn(0);
3729e25ed09SBarry Smith }
3739e25ed09SBarry Smith 
37430770e4dSSatish Balay #define MatSetValues_SeqAIJ_A_Private(row,col,value,addv) \
3750520107fSSatish Balay { \
3767cd84e04SBarry Smith     if (col <= lastcol1) low1 = 0; else high1 = nrow1; \
377fd3458f5SBarry Smith     lastcol1 = col;\
378fd3458f5SBarry Smith     while (high1-low1 > 5) { \
379fd3458f5SBarry Smith       t = (low1+high1)/2; \
380fd3458f5SBarry Smith       if (rp1[t] > col) high1 = t; \
381fd3458f5SBarry Smith       else             low1  = t; \
382ba4e3ef2SSatish Balay     } \
383fd3458f5SBarry Smith       for (_i=low1; _i<high1; _i++) { \
384fd3458f5SBarry Smith         if (rp1[_i] > col) break; \
385fd3458f5SBarry Smith         if (rp1[_i] == col) { \
386fd3458f5SBarry Smith           if (addv == ADD_VALUES) ap1[_i] += value;   \
387fd3458f5SBarry Smith           else                    ap1[_i] = value; \
38830770e4dSSatish Balay           goto a_noinsert; \
3890520107fSSatish Balay         } \
3900520107fSSatish Balay       }  \
391e44c0bd4SBarry Smith       if (value == 0.0 && ignorezeroentries) {low1 = 0; high1 = nrow1;goto a_noinsert;} \
392e44c0bd4SBarry Smith       if (nonew == 1) {low1 = 0; high1 = nrow1; goto a_noinsert;}		\
393e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) into matrix", row, col); \
394fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,am,1,nrow1,row,col,rmax1,aa,ai,aj,rp1,ap1,aimax,nonew,MatScalar); \
395669a8dbcSSatish Balay       N = nrow1++ - 1; a->nz++; high1++; \
3960520107fSSatish Balay       /* shift up all the later entries in this row */ \
3970520107fSSatish Balay       for (ii=N; ii>=_i; ii--) { \
398fd3458f5SBarry Smith         rp1[ii+1] = rp1[ii]; \
399fd3458f5SBarry Smith         ap1[ii+1] = ap1[ii]; \
4000520107fSSatish Balay       } \
401fd3458f5SBarry Smith       rp1[_i] = col;  \
402fd3458f5SBarry Smith       ap1[_i] = value;  \
40330770e4dSSatish Balay       a_noinsert: ; \
404fd3458f5SBarry Smith       ailen[row] = nrow1; \
4050520107fSSatish Balay }
4060a198c4cSBarry Smith 
407085a36d4SBarry Smith 
40830770e4dSSatish Balay #define MatSetValues_SeqAIJ_B_Private(row,col,value,addv) \
40930770e4dSSatish Balay { \
4107cd84e04SBarry Smith     if (col <= lastcol2) low2 = 0; else high2 = nrow2; \
411fd3458f5SBarry Smith     lastcol2 = col;\
412fd3458f5SBarry Smith     while (high2-low2 > 5) { \
413fd3458f5SBarry Smith       t = (low2+high2)/2; \
414fd3458f5SBarry Smith       if (rp2[t] > col) high2 = t; \
415fd3458f5SBarry Smith       else             low2  = t; \
416ba4e3ef2SSatish Balay     } \
417fd3458f5SBarry Smith     for (_i=low2; _i<high2; _i++) {		\
418fd3458f5SBarry Smith       if (rp2[_i] > col) break;			\
419fd3458f5SBarry Smith       if (rp2[_i] == col) {			      \
420fd3458f5SBarry Smith 	if (addv == ADD_VALUES) ap2[_i] += value;     \
421fd3458f5SBarry Smith 	else                    ap2[_i] = value;      \
42230770e4dSSatish Balay 	goto b_noinsert;			      \
42330770e4dSSatish Balay       }						      \
42430770e4dSSatish Balay     }							      \
425e44c0bd4SBarry Smith     if (value == 0.0 && ignorezeroentries) {low2 = 0; high2 = nrow2; goto b_noinsert;} \
426e44c0bd4SBarry Smith     if (nonew == 1) {low2 = 0; high2 = nrow2; goto b_noinsert;}		\
427e32f2f54SBarry Smith     if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) into matrix", row, col); \
428fef13f97SBarry Smith     MatSeqXAIJReallocateAIJ(B,bm,1,nrow2,row,col,rmax2,ba,bi,bj,rp2,ap2,bimax,nonew,MatScalar); \
429669a8dbcSSatish Balay     N = nrow2++ - 1; b->nz++; high2++;					\
43030770e4dSSatish Balay     /* shift up all the later entries in this row */			\
43130770e4dSSatish Balay     for (ii=N; ii>=_i; ii--) {						\
432fd3458f5SBarry Smith       rp2[ii+1] = rp2[ii];						\
433fd3458f5SBarry Smith       ap2[ii+1] = ap2[ii];						\
43430770e4dSSatish Balay     }									\
435fd3458f5SBarry Smith     rp2[_i] = col;							\
436fd3458f5SBarry Smith     ap2[_i] = value;							\
43730770e4dSSatish Balay     b_noinsert: ;								\
438fd3458f5SBarry Smith     bilen[row] = nrow2;							\
43930770e4dSSatish Balay }
44030770e4dSSatish Balay 
4414a2ae208SSatish Balay #undef __FUNCT__
4422fd7e33dSBarry Smith #define __FUNCT__ "MatSetValuesRow_MPIAIJ"
4432fd7e33dSBarry Smith PetscErrorCode MatSetValuesRow_MPIAIJ(Mat A,PetscInt row,const PetscScalar v[])
4442fd7e33dSBarry Smith {
4452fd7e33dSBarry Smith   Mat_MPIAIJ     *mat = (Mat_MPIAIJ*)A->data;
4462fd7e33dSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->A->data,*b = (Mat_SeqAIJ*)mat->B->data;
4472fd7e33dSBarry Smith   PetscErrorCode ierr;
4482fd7e33dSBarry Smith   PetscInt       l,*garray = mat->garray,diag;
4492fd7e33dSBarry Smith 
4502fd7e33dSBarry Smith   PetscFunctionBegin;
4512fd7e33dSBarry Smith   /* code only works for square matrices A */
4522fd7e33dSBarry Smith 
4532fd7e33dSBarry Smith   /* find size of row to the left of the diagonal part */
4542fd7e33dSBarry Smith   ierr = MatGetOwnershipRange(A,&diag,0);CHKERRQ(ierr);
4552fd7e33dSBarry Smith   row  = row - diag;
4562fd7e33dSBarry Smith   for (l=0; l<b->i[row+1]-b->i[row]; l++) {
4572fd7e33dSBarry Smith     if (garray[b->j[b->i[row]+l]] > diag) break;
4582fd7e33dSBarry Smith   }
4592fd7e33dSBarry Smith   ierr = PetscMemcpy(b->a+b->i[row],v,l*sizeof(PetscScalar));CHKERRQ(ierr);
4602fd7e33dSBarry Smith 
4612fd7e33dSBarry Smith   /* diagonal part */
4622fd7e33dSBarry Smith   ierr = PetscMemcpy(a->a+a->i[row],v+l,(a->i[row+1]-a->i[row])*sizeof(PetscScalar));CHKERRQ(ierr);
4632fd7e33dSBarry Smith 
4642fd7e33dSBarry Smith   /* right of diagonal part */
4652fd7e33dSBarry Smith   ierr = PetscMemcpy(b->a+b->i[row]+l,v+l+a->i[row+1]-a->i[row],(b->i[row+1]-b->i[row]-l)*sizeof(PetscScalar));CHKERRQ(ierr);
4662fd7e33dSBarry Smith   PetscFunctionReturn(0);
4672fd7e33dSBarry Smith }
4682fd7e33dSBarry Smith 
4692fd7e33dSBarry Smith #undef __FUNCT__
4704a2ae208SSatish Balay #define __FUNCT__ "MatSetValues_MPIAIJ"
471b1d57f15SBarry Smith PetscErrorCode MatSetValues_MPIAIJ(Mat mat,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode addv)
4728a729477SBarry Smith {
47344a69424SLois Curfman McInnes   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)mat->data;
47487828ca2SBarry Smith   PetscScalar    value;
475dfbe8321SBarry Smith   PetscErrorCode ierr;
476d0f46423SBarry Smith   PetscInt       i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend;
477d0f46423SBarry Smith   PetscInt       cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col;
478ace3abfcSBarry Smith   PetscBool      roworiented = aij->roworiented;
4798a729477SBarry Smith 
4800520107fSSatish Balay   /* Some Variables required in the macro */
4814ee7247eSSatish Balay   Mat            A = aij->A;
4824ee7247eSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
48357809a77SBarry Smith   PetscInt       *aimax = a->imax,*ai = a->i,*ailen = a->ilen,*aj = a->j;
484a77337e4SBarry Smith   MatScalar      *aa = a->a;
485ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
48630770e4dSSatish Balay   Mat            B = aij->B;
48730770e4dSSatish Balay   Mat_SeqAIJ     *b = (Mat_SeqAIJ*)B->data;
488d0f46423SBarry Smith   PetscInt       *bimax = b->imax,*bi = b->i,*bilen = b->ilen,*bj = b->j,bm = aij->B->rmap->n,am = aij->A->rmap->n;
489a77337e4SBarry Smith   MatScalar      *ba = b->a;
49030770e4dSSatish Balay 
491fd3458f5SBarry Smith   PetscInt       *rp1,*rp2,ii,nrow1,nrow2,_i,rmax1,rmax2,N,low1,high1,low2,high2,t,lastcol1,lastcol2;
4928d76821aSHong Zhang   PetscInt       nonew;
493a77337e4SBarry Smith   MatScalar      *ap1,*ap2;
4944ee7247eSSatish Balay 
4953a40ed3dSBarry Smith   PetscFunctionBegin;
49671fd2e92SBarry Smith   if (v) PetscValidScalarPointer(v,6);
4978a729477SBarry Smith   for (i=0; i<m; i++) {
4985ef9f2a5SBarry Smith     if (im[i] < 0) continue;
4992515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
500e32f2f54SBarry Smith     if (im[i] >= mat->rmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",im[i],mat->rmap->N-1);
5010a198c4cSBarry Smith #endif
5024b0e389bSBarry Smith     if (im[i] >= rstart && im[i] < rend) {
5034b0e389bSBarry Smith       row      = im[i] - rstart;
504fd3458f5SBarry Smith       lastcol1 = -1;
505fd3458f5SBarry Smith       rp1      = aj + ai[row];
506fd3458f5SBarry Smith       ap1      = aa + ai[row];
507fd3458f5SBarry Smith       rmax1    = aimax[row];
508fd3458f5SBarry Smith       nrow1    = ailen[row];
509fd3458f5SBarry Smith       low1     = 0;
510fd3458f5SBarry Smith       high1    = nrow1;
511fd3458f5SBarry Smith       lastcol2 = -1;
512fd3458f5SBarry Smith       rp2      = bj + bi[row];
513d498b1e9SBarry Smith       ap2      = ba + bi[row];
514fd3458f5SBarry Smith       rmax2    = bimax[row];
515d498b1e9SBarry Smith       nrow2    = bilen[row];
516fd3458f5SBarry Smith       low2     = 0;
517fd3458f5SBarry Smith       high2    = nrow2;
518fd3458f5SBarry Smith 
5191eb62cbbSBarry Smith       for (j=0; j<n; j++) {
52016371a99SBarry Smith         if (v) {if (roworiented) value = v[i*n+j]; else value = v[i+j*m];} else value = 0.0;
521abc0a331SBarry Smith         if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue;
522fd3458f5SBarry Smith         if (in[j] >= cstart && in[j] < cend){
523fd3458f5SBarry Smith           col = in[j] - cstart;
5248d76821aSHong Zhang           nonew = a->nonew;
52530770e4dSSatish Balay           MatSetValues_SeqAIJ_A_Private(row,col,value,addv);
526273d9f13SBarry Smith         } else if (in[j] < 0) continue;
5272515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
528cb9801acSJed Brown         else if (in[j] >= mat->cmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[j],mat->cmap->N-1);
5290a198c4cSBarry Smith #endif
5301eb62cbbSBarry Smith         else {
531227d817aSBarry Smith           if (mat->was_assembled) {
532905e6a2fSBarry Smith             if (!aij->colmap) {
533ab9863d7SBarry Smith               ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr);
534905e6a2fSBarry Smith             }
535aa482453SBarry Smith #if defined (PETSC_USE_CTABLE)
5360f5bd95cSBarry Smith             ierr = PetscTableFind(aij->colmap,in[j]+1,&col);CHKERRQ(ierr);
537fa46199cSSatish Balay 	    col--;
538b1fc9764SSatish Balay #else
539905e6a2fSBarry Smith             col = aij->colmap[in[j]] - 1;
540b1fc9764SSatish Balay #endif
541ec8511deSBarry Smith             if (col < 0 && !((Mat_SeqAIJ*)(aij->A->data))->nonew) {
542ab9863d7SBarry Smith               ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr);
5434b0e389bSBarry Smith               col =  in[j];
5449bf004c3SSatish Balay               /* Reinitialize the variables required by MatSetValues_SeqAIJ_B_Private() */
545f9508a3cSSatish Balay               B = aij->B;
546f9508a3cSSatish Balay               b = (Mat_SeqAIJ*)B->data;
547e44c0bd4SBarry Smith               bimax = b->imax; bi = b->i; bilen = b->ilen; bj = b->j; ba = b->a;
548d498b1e9SBarry Smith               rp2      = bj + bi[row];
549d498b1e9SBarry Smith               ap2      = ba + bi[row];
550d498b1e9SBarry Smith               rmax2    = bimax[row];
551d498b1e9SBarry Smith               nrow2    = bilen[row];
552d498b1e9SBarry Smith               low2     = 0;
553d498b1e9SBarry Smith               high2    = nrow2;
554d0f46423SBarry Smith               bm       = aij->B->rmap->n;
555f9508a3cSSatish Balay               ba = b->a;
556d6dfbf8fSBarry Smith             }
557c48de900SBarry Smith           } else col = in[j];
5588d76821aSHong Zhang           nonew = b->nonew;
55930770e4dSSatish Balay           MatSetValues_SeqAIJ_B_Private(row,col,value,addv);
5601eb62cbbSBarry Smith         }
5611eb62cbbSBarry Smith       }
5625ef9f2a5SBarry Smith     } else {
5634cb17eb5SBarry Smith       if (mat->nooffprocentries) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Setting off process row %D even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set",im[i]);
56490f02eecSBarry Smith       if (!aij->donotstash) {
5655080c13bSMatthew G Knepley         mat->assembled = PETSC_FALSE;
566d36fbae8SSatish Balay         if (roworiented) {
567ace3abfcSBarry Smith           ierr = MatStashValuesRow_Private(&mat->stash,im[i],n,in,v+i*n,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr);
568d36fbae8SSatish Balay         } else {
569ace3abfcSBarry Smith           ierr = MatStashValuesCol_Private(&mat->stash,im[i],n,in,v+i,m,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr);
5704b0e389bSBarry Smith         }
5711eb62cbbSBarry Smith       }
5728a729477SBarry Smith     }
57390f02eecSBarry Smith   }
5743a40ed3dSBarry Smith   PetscFunctionReturn(0);
5758a729477SBarry Smith }
5768a729477SBarry Smith 
5774a2ae208SSatish Balay #undef __FUNCT__
5784a2ae208SSatish Balay #define __FUNCT__ "MatGetValues_MPIAIJ"
579b1d57f15SBarry Smith PetscErrorCode MatGetValues_MPIAIJ(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
580b49de8d1SLois Curfman McInnes {
581b49de8d1SLois Curfman McInnes   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)mat->data;
582dfbe8321SBarry Smith   PetscErrorCode ierr;
583d0f46423SBarry Smith   PetscInt       i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend;
584d0f46423SBarry Smith   PetscInt       cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col;
585b49de8d1SLois Curfman McInnes 
5863a40ed3dSBarry Smith   PetscFunctionBegin;
587b49de8d1SLois Curfman McInnes   for (i=0; i<m; i++) {
588e32f2f54SBarry Smith     if (idxm[i] < 0) continue; /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",idxm[i]);*/
589e32f2f54SBarry Smith     if (idxm[i] >= mat->rmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm[i],mat->rmap->N-1);
590b49de8d1SLois Curfman McInnes     if (idxm[i] >= rstart && idxm[i] < rend) {
591b49de8d1SLois Curfman McInnes       row = idxm[i] - rstart;
592b49de8d1SLois Curfman McInnes       for (j=0; j<n; j++) {
593e32f2f54SBarry Smith         if (idxn[j] < 0) continue; /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",idxn[j]); */
594e32f2f54SBarry Smith         if (idxn[j] >= mat->cmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",idxn[j],mat->cmap->N-1);
595b49de8d1SLois Curfman McInnes         if (idxn[j] >= cstart && idxn[j] < cend){
596b49de8d1SLois Curfman McInnes           col = idxn[j] - cstart;
597b49de8d1SLois Curfman McInnes           ierr = MatGetValues(aij->A,1,&row,1,&col,v+i*n+j);CHKERRQ(ierr);
598fa852ad4SSatish Balay         } else {
599905e6a2fSBarry Smith           if (!aij->colmap) {
600ab9863d7SBarry Smith             ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr);
601905e6a2fSBarry Smith           }
602aa482453SBarry Smith #if defined (PETSC_USE_CTABLE)
6030f5bd95cSBarry Smith           ierr = PetscTableFind(aij->colmap,idxn[j]+1,&col);CHKERRQ(ierr);
604fa46199cSSatish Balay           col --;
605b1fc9764SSatish Balay #else
606905e6a2fSBarry Smith           col = aij->colmap[idxn[j]] - 1;
607b1fc9764SSatish Balay #endif
608e60e1c95SSatish Balay           if ((col < 0) || (aij->garray[col] != idxn[j])) *(v+i*n+j) = 0.0;
609d9d09a02SSatish Balay           else {
610b49de8d1SLois Curfman McInnes             ierr = MatGetValues(aij->B,1,&row,1,&col,v+i*n+j);CHKERRQ(ierr);
611b49de8d1SLois Curfman McInnes           }
612b49de8d1SLois Curfman McInnes         }
613b49de8d1SLois Curfman McInnes       }
614a8c6a408SBarry Smith     } else {
615e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only local values currently supported");
616b49de8d1SLois Curfman McInnes     }
617b49de8d1SLois Curfman McInnes   }
6183a40ed3dSBarry Smith   PetscFunctionReturn(0);
619b49de8d1SLois Curfman McInnes }
620bc5ccf88SSatish Balay 
621bd0c2dcbSBarry Smith extern PetscErrorCode MatMultDiagonalBlock_MPIAIJ(Mat,Vec,Vec);
622bd0c2dcbSBarry Smith 
6234a2ae208SSatish Balay #undef __FUNCT__
6244a2ae208SSatish Balay #define __FUNCT__ "MatAssemblyBegin_MPIAIJ"
625dfbe8321SBarry Smith PetscErrorCode MatAssemblyBegin_MPIAIJ(Mat mat,MatAssemblyType mode)
626bc5ccf88SSatish Balay {
627bc5ccf88SSatish Balay   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)mat->data;
628dfbe8321SBarry Smith   PetscErrorCode ierr;
629b1d57f15SBarry Smith   PetscInt       nstash,reallocs;
630bc5ccf88SSatish Balay   InsertMode     addv;
631bc5ccf88SSatish Balay 
632bc5ccf88SSatish Balay   PetscFunctionBegin;
6334cb17eb5SBarry Smith   if (aij->donotstash || mat->nooffprocentries) {
634bc5ccf88SSatish Balay     PetscFunctionReturn(0);
635bc5ccf88SSatish Balay   }
636bc5ccf88SSatish Balay 
637bc5ccf88SSatish Balay   /* make sure all processors are either in INSERTMODE or ADDMODE */
6387adad957SLisandro Dalcin   ierr = MPI_Allreduce(&mat->insertmode,&addv,1,MPI_INT,MPI_BOR,((PetscObject)mat)->comm);CHKERRQ(ierr);
639e7e72b3dSBarry Smith   if (addv == (ADD_VALUES|INSERT_VALUES)) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_ARG_WRONGSTATE,"Some processors inserted others added");
640bc5ccf88SSatish Balay   mat->insertmode = addv; /* in case this processor had no cache */
641bc5ccf88SSatish Balay 
642d0f46423SBarry Smith   ierr = MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range);CHKERRQ(ierr);
6438798bf22SSatish Balay   ierr = MatStashGetInfo_Private(&mat->stash,&nstash,&reallocs);CHKERRQ(ierr);
644ae15b995SBarry Smith   ierr = PetscInfo2(aij->A,"Stash has %D entries, uses %D mallocs.\n",nstash,reallocs);CHKERRQ(ierr);
645bc5ccf88SSatish Balay   PetscFunctionReturn(0);
646bc5ccf88SSatish Balay }
647bc5ccf88SSatish Balay 
6484a2ae208SSatish Balay #undef __FUNCT__
6494a2ae208SSatish Balay #define __FUNCT__ "MatAssemblyEnd_MPIAIJ"
650dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_MPIAIJ(Mat mat,MatAssemblyType mode)
651bc5ccf88SSatish Balay {
652bc5ccf88SSatish Balay   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)mat->data;
65391c97fd4SSatish Balay   Mat_SeqAIJ     *a=(Mat_SeqAIJ *)aij->A->data;
6546849ba73SBarry Smith   PetscErrorCode ierr;
655b1d57f15SBarry Smith   PetscMPIInt    n;
656b1d57f15SBarry Smith   PetscInt       i,j,rstart,ncols,flg;
657e44c0bd4SBarry Smith   PetscInt       *row,*col;
658ace3abfcSBarry Smith   PetscBool      other_disassembled;
65987828ca2SBarry Smith   PetscScalar    *val;
660bc5ccf88SSatish Balay   InsertMode     addv = mat->insertmode;
661bc5ccf88SSatish Balay 
66291c97fd4SSatish Balay   /* do not use 'b = (Mat_SeqAIJ *)aij->B->data' as B can be reset in disassembly */
663bc5ccf88SSatish Balay   PetscFunctionBegin;
6644cb17eb5SBarry Smith   if (!aij->donotstash && !mat->nooffprocentries) {
665a2d1c673SSatish Balay     while (1) {
6668798bf22SSatish Balay       ierr = MatStashScatterGetMesg_Private(&mat->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr);
667a2d1c673SSatish Balay       if (!flg) break;
668a2d1c673SSatish Balay 
669bc5ccf88SSatish Balay       for (i=0; i<n;) {
670bc5ccf88SSatish Balay         /* Now identify the consecutive vals belonging to the same row */
671bc5ccf88SSatish Balay         for (j=i,rstart=row[j]; j<n; j++) { if (row[j] != rstart) break; }
672bc5ccf88SSatish Balay         if (j < n) ncols = j-i;
673bc5ccf88SSatish Balay         else       ncols = n-i;
674bc5ccf88SSatish Balay         /* Now assemble all these values with a single function call */
675bc5ccf88SSatish Balay         ierr = MatSetValues_MPIAIJ(mat,1,row+i,ncols,col+i,val+i,addv);CHKERRQ(ierr);
676bc5ccf88SSatish Balay         i = j;
677bc5ccf88SSatish Balay       }
678bc5ccf88SSatish Balay     }
6798798bf22SSatish Balay     ierr = MatStashScatterEnd_Private(&mat->stash);CHKERRQ(ierr);
680bc5ccf88SSatish Balay   }
681bc5ccf88SSatish Balay   ierr = MatAssemblyBegin(aij->A,mode);CHKERRQ(ierr);
682bc5ccf88SSatish Balay   ierr = MatAssemblyEnd(aij->A,mode);CHKERRQ(ierr);
683bc5ccf88SSatish Balay 
684bc5ccf88SSatish Balay   /* determine if any processor has disassembled, if so we must
685bc5ccf88SSatish Balay      also disassemble ourselfs, in order that we may reassemble. */
686bc5ccf88SSatish Balay   /*
687bc5ccf88SSatish Balay      if nonzero structure of submatrix B cannot change then we know that
688bc5ccf88SSatish Balay      no processor disassembled thus we can skip this stuff
689bc5ccf88SSatish Balay   */
690bc5ccf88SSatish Balay   if (!((Mat_SeqAIJ*)aij->B->data)->nonew)  {
6917adad957SLisandro Dalcin     ierr = MPI_Allreduce(&mat->was_assembled,&other_disassembled,1,MPI_INT,MPI_PROD,((PetscObject)mat)->comm);CHKERRQ(ierr);
692bc5ccf88SSatish Balay     if (mat->was_assembled && !other_disassembled) {
693ab9863d7SBarry Smith       ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr);
694ad59fb31SSatish Balay     }
695ad59fb31SSatish Balay   }
696bc5ccf88SSatish Balay   if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) {
697bc5ccf88SSatish Balay     ierr = MatSetUpMultiply_MPIAIJ(mat);CHKERRQ(ierr);
698bc5ccf88SSatish Balay   }
6994e0d8c25SBarry Smith   ierr = MatSetOption(aij->B,MAT_USE_INODES,PETSC_FALSE);CHKERRQ(ierr);
7004e35b6f3SSatish Balay   ierr = MatSetOption(aij->B,MAT_CHECK_COMPRESSED_ROW,PETSC_FALSE);CHKERRQ(ierr);
701bc5ccf88SSatish Balay   ierr = MatAssemblyBegin(aij->B,mode);CHKERRQ(ierr);
702bc5ccf88SSatish Balay   ierr = MatAssemblyEnd(aij->B,mode);CHKERRQ(ierr);
703bc5ccf88SSatish Balay 
7041d79065fSBarry Smith   ierr = PetscFree2(aij->rowvalues,aij->rowindices);CHKERRQ(ierr);
705606d414cSSatish Balay   aij->rowvalues = 0;
706a30b2313SHong Zhang 
707a30b2313SHong Zhang   /* used by MatAXPY() */
70891c97fd4SSatish Balay   a->xtoy = 0; ((Mat_SeqAIJ *)aij->B->data)->xtoy = 0;  /* b->xtoy = 0 */
70991c97fd4SSatish Balay   a->XtoY = 0; ((Mat_SeqAIJ *)aij->B->data)->XtoY = 0;  /* b->XtoY = 0 */
710a30b2313SHong Zhang 
7116bf464f9SBarry Smith   ierr = VecDestroy(&aij->diag);CHKERRQ(ierr);
712bd0c2dcbSBarry Smith   if (a->inode.size) mat->ops->multdiagonalblock = MatMultDiagonalBlock_MPIAIJ;
713bc5ccf88SSatish Balay   PetscFunctionReturn(0);
714bc5ccf88SSatish Balay }
715bc5ccf88SSatish Balay 
7164a2ae208SSatish Balay #undef __FUNCT__
7174a2ae208SSatish Balay #define __FUNCT__ "MatZeroEntries_MPIAIJ"
718dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_MPIAIJ(Mat A)
7191eb62cbbSBarry Smith {
72044a69424SLois Curfman McInnes   Mat_MPIAIJ     *l = (Mat_MPIAIJ*)A->data;
721dfbe8321SBarry Smith   PetscErrorCode ierr;
7223a40ed3dSBarry Smith 
7233a40ed3dSBarry Smith   PetscFunctionBegin;
72478b31e54SBarry Smith   ierr = MatZeroEntries(l->A);CHKERRQ(ierr);
72578b31e54SBarry Smith   ierr = MatZeroEntries(l->B);CHKERRQ(ierr);
7263a40ed3dSBarry Smith   PetscFunctionReturn(0);
7271eb62cbbSBarry Smith }
7281eb62cbbSBarry Smith 
7294a2ae208SSatish Balay #undef __FUNCT__
7304a2ae208SSatish Balay #define __FUNCT__ "MatZeroRows_MPIAIJ"
7312b40b63fSBarry Smith PetscErrorCode MatZeroRows_MPIAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
7321eb62cbbSBarry Smith {
73344a69424SLois Curfman McInnes   Mat_MPIAIJ        *l = (Mat_MPIAIJ*)A->data;
7346849ba73SBarry Smith   PetscErrorCode    ierr;
7357adad957SLisandro Dalcin   PetscMPIInt       size = l->size,imdex,n,rank = l->rank,tag = ((PetscObject)A)->tag,lastidx = -1;
736d0f46423SBarry Smith   PetscInt          i,*owners = A->rmap->range;
737b1d57f15SBarry Smith   PetscInt          *nprocs,j,idx,nsends,row;
738b1d57f15SBarry Smith   PetscInt          nmax,*svalues,*starts,*owner,nrecvs;
739b1d57f15SBarry Smith   PetscInt          *rvalues,count,base,slen,*source;
740d0f46423SBarry Smith   PetscInt          *lens,*lrows,*values,rstart=A->rmap->rstart;
7417adad957SLisandro Dalcin   MPI_Comm          comm = ((PetscObject)A)->comm;
7421eb62cbbSBarry Smith   MPI_Request       *send_waits,*recv_waits;
7431eb62cbbSBarry Smith   MPI_Status        recv_status,*send_status;
74497b48c8fSBarry Smith   const PetscScalar *xx;
74597b48c8fSBarry Smith   PetscScalar       *bb;
7466543fbbaSBarry Smith #if defined(PETSC_DEBUG)
747ace3abfcSBarry Smith   PetscBool      found = PETSC_FALSE;
7486543fbbaSBarry Smith #endif
7491eb62cbbSBarry Smith 
7503a40ed3dSBarry Smith   PetscFunctionBegin;
7511eb62cbbSBarry Smith   /*  first count number of contributors to each processor */
752b1d57f15SBarry Smith   ierr = PetscMalloc(2*size*sizeof(PetscInt),&nprocs);CHKERRQ(ierr);
753b1d57f15SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
754b1d57f15SBarry Smith   ierr = PetscMalloc((N+1)*sizeof(PetscInt),&owner);CHKERRQ(ierr); /* see note*/
7556543fbbaSBarry Smith   j = 0;
7561eb62cbbSBarry Smith   for (i=0; i<N; i++) {
7576543fbbaSBarry Smith     if (lastidx > (idx = rows[i])) j = 0;
7586543fbbaSBarry Smith     lastidx = idx;
7596543fbbaSBarry Smith     for (; j<size; j++) {
7601eb62cbbSBarry Smith       if (idx >= owners[j] && idx < owners[j+1]) {
7616543fbbaSBarry Smith         nprocs[2*j]++;
7626543fbbaSBarry Smith         nprocs[2*j+1] = 1;
7636543fbbaSBarry Smith         owner[i] = j;
7646543fbbaSBarry Smith #if defined(PETSC_DEBUG)
7656543fbbaSBarry Smith         found = PETSC_TRUE;
7666543fbbaSBarry Smith #endif
7676543fbbaSBarry Smith         break;
7681eb62cbbSBarry Smith       }
7691eb62cbbSBarry Smith     }
7706543fbbaSBarry Smith #if defined(PETSC_DEBUG)
771e32f2f54SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index out of range");
7726543fbbaSBarry Smith     found = PETSC_FALSE;
7736543fbbaSBarry Smith #endif
7741eb62cbbSBarry Smith   }
775c1dc657dSBarry Smith   nsends = 0;  for (i=0; i<size; i++) { nsends += nprocs[2*i+1];}
7761eb62cbbSBarry Smith 
7777367270fSBarry Smith   if (A->nooffproczerorows) {
7787367270fSBarry Smith     if (nsends > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"You called MatSetOption(,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) but set an off process zero row");
7797367270fSBarry Smith     nrecvs = nsends;
7807367270fSBarry Smith     nmax   = N;
7817367270fSBarry Smith   } else {
7821eb62cbbSBarry Smith     /* inform other processors of number of messages and max length*/
783c1dc657dSBarry Smith     ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
7847367270fSBarry Smith   }
7851eb62cbbSBarry Smith 
7861eb62cbbSBarry Smith   /* post receives:   */
787b1d57f15SBarry Smith   ierr = PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(PetscInt),&rvalues);CHKERRQ(ierr);
788b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
7891eb62cbbSBarry Smith   for (i=0; i<nrecvs; i++) {
790b1d57f15SBarry Smith     ierr = MPI_Irecv(rvalues+nmax*i,nmax,MPIU_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr);
7911eb62cbbSBarry Smith   }
7921eb62cbbSBarry Smith 
7931eb62cbbSBarry Smith   /* do sends:
7941eb62cbbSBarry Smith       1) starts[i] gives the starting index in svalues for stuff going to
7951eb62cbbSBarry Smith          the ith processor
7961eb62cbbSBarry Smith   */
797b1d57f15SBarry Smith   ierr = PetscMalloc((N+1)*sizeof(PetscInt),&svalues);CHKERRQ(ierr);
798b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
799b1d57f15SBarry Smith   ierr = PetscMalloc((size+1)*sizeof(PetscInt),&starts);CHKERRQ(ierr);
8001eb62cbbSBarry Smith   starts[0] = 0;
801c1dc657dSBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + nprocs[2*i-2];}
8021eb62cbbSBarry Smith   for (i=0; i<N; i++) {
8031eb62cbbSBarry Smith     svalues[starts[owner[i]]++] = rows[i];
8041eb62cbbSBarry Smith   }
8051eb62cbbSBarry Smith 
8061eb62cbbSBarry Smith   starts[0] = 0;
807c1dc657dSBarry Smith   for (i=1; i<size+1; i++) { starts[i] = starts[i-1] + nprocs[2*i-2];}
8081eb62cbbSBarry Smith   count = 0;
80917699dbbSLois Curfman McInnes   for (i=0; i<size; i++) {
810c1dc657dSBarry Smith     if (nprocs[2*i+1]) {
811b1d57f15SBarry Smith       ierr = MPI_Isend(svalues+starts[i],nprocs[2*i],MPIU_INT,i,tag,comm,send_waits+count++);CHKERRQ(ierr);
8121eb62cbbSBarry Smith     }
8131eb62cbbSBarry Smith   }
814606d414cSSatish Balay   ierr = PetscFree(starts);CHKERRQ(ierr);
8151eb62cbbSBarry Smith 
81617699dbbSLois Curfman McInnes   base = owners[rank];
8171eb62cbbSBarry Smith 
8181eb62cbbSBarry Smith   /*  wait on receives */
8191d79065fSBarry Smith   ierr   = PetscMalloc2(nrecvs,PetscInt,&lens,nrecvs,PetscInt,&source);CHKERRQ(ierr);
8201eb62cbbSBarry Smith   count  = nrecvs; slen = 0;
8211eb62cbbSBarry Smith   while (count) {
822ca161407SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
8231eb62cbbSBarry Smith     /* unpack receives into our local space */
824b1d57f15SBarry Smith     ierr = MPI_Get_count(&recv_status,MPIU_INT,&n);CHKERRQ(ierr);
825d6dfbf8fSBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
826d6dfbf8fSBarry Smith     lens[imdex]    = n;
8271eb62cbbSBarry Smith     slen          += n;
8281eb62cbbSBarry Smith     count--;
8291eb62cbbSBarry Smith   }
830606d414cSSatish Balay   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
8311eb62cbbSBarry Smith 
8321eb62cbbSBarry Smith   /* move the data into the send scatter */
833b1d57f15SBarry Smith   ierr = PetscMalloc((slen+1)*sizeof(PetscInt),&lrows);CHKERRQ(ierr);
8341eb62cbbSBarry Smith   count = 0;
8351eb62cbbSBarry Smith   for (i=0; i<nrecvs; i++) {
8361eb62cbbSBarry Smith     values = rvalues + i*nmax;
8371eb62cbbSBarry Smith     for (j=0; j<lens[i]; j++) {
8381eb62cbbSBarry Smith       lrows[count++] = values[j] - base;
8391eb62cbbSBarry Smith     }
8401eb62cbbSBarry Smith   }
841606d414cSSatish Balay   ierr = PetscFree(rvalues);CHKERRQ(ierr);
8421d79065fSBarry Smith   ierr = PetscFree2(lens,source);CHKERRQ(ierr);
843606d414cSSatish Balay   ierr = PetscFree(owner);CHKERRQ(ierr);
844606d414cSSatish Balay   ierr = PetscFree(nprocs);CHKERRQ(ierr);
8451eb62cbbSBarry Smith 
84697b48c8fSBarry Smith   /* fix right hand side if needed */
84797b48c8fSBarry Smith   if (x && b) {
84897b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
84997b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
850564f14d6SBarry Smith     for (i=0; i<slen; i++) {
85197b48c8fSBarry Smith       bb[lrows[i]] = diag*xx[lrows[i]];
85297b48c8fSBarry Smith     }
85397b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
85497b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
85597b48c8fSBarry Smith   }
8566eb55b6aSBarry Smith   /*
8576eb55b6aSBarry Smith         Zero the required rows. If the "diagonal block" of the matrix
858a8c7a070SBarry Smith      is square and the user wishes to set the diagonal we use separate
8596eb55b6aSBarry Smith      code so that MatSetValues() is not called for each diagonal allocating
8606eb55b6aSBarry Smith      new memory, thus calling lots of mallocs and slowing things down.
8616eb55b6aSBarry Smith 
8626eb55b6aSBarry Smith   */
863e2d53e46SBarry Smith   /* must zero l->B before l->A because the (diag) case below may put values into l->B*/
8642b40b63fSBarry Smith   ierr = MatZeroRows(l->B,slen,lrows,0.0,0,0);CHKERRQ(ierr);
865d0f46423SBarry Smith   if ((diag != 0.0) && (l->A->rmap->N == l->A->cmap->N)) {
8662b40b63fSBarry Smith     ierr = MatZeroRows(l->A,slen,lrows,diag,0,0);CHKERRQ(ierr);
867f4df32b1SMatthew Knepley   } else if (diag != 0.0) {
8682b40b63fSBarry Smith     ierr = MatZeroRows(l->A,slen,lrows,0.0,0,0);CHKERRQ(ierr);
869fa46199cSSatish Balay     if (((Mat_SeqAIJ*)l->A->data)->nonew) {
870e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatZeroRows() on rectangular matrices cannot be used with the Mat options\n\
871512a5fc5SBarry Smith MAT_NEW_NONZERO_LOCATIONS,MAT_NEW_NONZERO_LOCATION_ERR,MAT_NEW_NONZERO_ALLOCATION_ERR");
8726525c446SSatish Balay     }
873e2d53e46SBarry Smith     for (i = 0; i < slen; i++) {
874e2d53e46SBarry Smith       row  = lrows[i] + rstart;
875f4df32b1SMatthew Knepley       ierr = MatSetValues(A,1,&row,1,&row,&diag,INSERT_VALUES);CHKERRQ(ierr);
876e2d53e46SBarry Smith     }
877e2d53e46SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
878e2d53e46SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8796eb55b6aSBarry Smith   } else {
8802b40b63fSBarry Smith     ierr = MatZeroRows(l->A,slen,lrows,0.0,0,0);CHKERRQ(ierr);
8816eb55b6aSBarry Smith   }
882606d414cSSatish Balay   ierr = PetscFree(lrows);CHKERRQ(ierr);
88372dacd9aSBarry Smith 
8841eb62cbbSBarry Smith   /* wait on sends */
8851eb62cbbSBarry Smith   if (nsends) {
886b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
887ca161407SBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
888606d414cSSatish Balay     ierr = PetscFree(send_status);CHKERRQ(ierr);
8891eb62cbbSBarry Smith   }
890606d414cSSatish Balay   ierr = PetscFree(send_waits);CHKERRQ(ierr);
891606d414cSSatish Balay   ierr = PetscFree(svalues);CHKERRQ(ierr);
8923a40ed3dSBarry Smith   PetscFunctionReturn(0);
8931eb62cbbSBarry Smith }
8941eb62cbbSBarry Smith 
8954a2ae208SSatish Balay #undef __FUNCT__
8969c7c4993SBarry Smith #define __FUNCT__ "MatZeroRowsColumns_MPIAIJ"
8979c7c4993SBarry Smith PetscErrorCode MatZeroRowsColumns_MPIAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
8989c7c4993SBarry Smith {
8999c7c4993SBarry Smith   Mat_MPIAIJ        *l = (Mat_MPIAIJ*)A->data;
9009c7c4993SBarry Smith   PetscErrorCode    ierr;
9019c7c4993SBarry Smith   PetscMPIInt       size = l->size,imdex,n,rank = l->rank,tag = ((PetscObject)A)->tag,lastidx = -1;
9029c7c4993SBarry Smith   PetscInt          i,*owners = A->rmap->range;
903564f14d6SBarry Smith   PetscInt          *nprocs,j,idx,nsends;
9049c7c4993SBarry Smith   PetscInt          nmax,*svalues,*starts,*owner,nrecvs;
9059c7c4993SBarry Smith   PetscInt          *rvalues,count,base,slen,*source;
906564f14d6SBarry Smith   PetscInt          *lens,*lrows,*values,m;
9079c7c4993SBarry Smith   MPI_Comm          comm = ((PetscObject)A)->comm;
9089c7c4993SBarry Smith   MPI_Request       *send_waits,*recv_waits;
9099c7c4993SBarry Smith   MPI_Status        recv_status,*send_status;
9109c7c4993SBarry Smith   const PetscScalar *xx;
911564f14d6SBarry Smith   PetscScalar       *bb,*mask;
912564f14d6SBarry Smith   Vec               xmask,lmask;
913564f14d6SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*)l->B->data;
914564f14d6SBarry Smith   const PetscInt    *aj, *ii,*ridx;
915564f14d6SBarry Smith   PetscScalar       *aa;
9169c7c4993SBarry Smith #if defined(PETSC_DEBUG)
9179c7c4993SBarry Smith   PetscBool         found = PETSC_FALSE;
9189c7c4993SBarry Smith #endif
9199c7c4993SBarry Smith 
9209c7c4993SBarry Smith   PetscFunctionBegin;
9219c7c4993SBarry Smith   /*  first count number of contributors to each processor */
9229c7c4993SBarry Smith   ierr = PetscMalloc(2*size*sizeof(PetscInt),&nprocs);CHKERRQ(ierr);
9239c7c4993SBarry Smith   ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
9249c7c4993SBarry Smith   ierr = PetscMalloc((N+1)*sizeof(PetscInt),&owner);CHKERRQ(ierr); /* see note*/
9259c7c4993SBarry Smith   j = 0;
9269c7c4993SBarry Smith   for (i=0; i<N; i++) {
9279c7c4993SBarry Smith     if (lastidx > (idx = rows[i])) j = 0;
9289c7c4993SBarry Smith     lastidx = idx;
9299c7c4993SBarry Smith     for (; j<size; j++) {
9309c7c4993SBarry Smith       if (idx >= owners[j] && idx < owners[j+1]) {
9319c7c4993SBarry Smith         nprocs[2*j]++;
9329c7c4993SBarry Smith         nprocs[2*j+1] = 1;
9339c7c4993SBarry Smith         owner[i] = j;
9349c7c4993SBarry Smith #if defined(PETSC_DEBUG)
9359c7c4993SBarry Smith         found = PETSC_TRUE;
9369c7c4993SBarry Smith #endif
9379c7c4993SBarry Smith         break;
9389c7c4993SBarry Smith       }
9399c7c4993SBarry Smith     }
9409c7c4993SBarry Smith #if defined(PETSC_DEBUG)
9419c7c4993SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index out of range");
9429c7c4993SBarry Smith     found = PETSC_FALSE;
9439c7c4993SBarry Smith #endif
9449c7c4993SBarry Smith   }
9459c7c4993SBarry Smith   nsends = 0;  for (i=0; i<size; i++) { nsends += nprocs[2*i+1];}
9469c7c4993SBarry Smith 
9479c7c4993SBarry Smith   /* inform other processors of number of messages and max length*/
9489c7c4993SBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
9499c7c4993SBarry Smith 
9509c7c4993SBarry Smith   /* post receives:   */
9519c7c4993SBarry Smith   ierr = PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(PetscInt),&rvalues);CHKERRQ(ierr);
9529c7c4993SBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
9539c7c4993SBarry Smith   for (i=0; i<nrecvs; i++) {
9549c7c4993SBarry Smith     ierr = MPI_Irecv(rvalues+nmax*i,nmax,MPIU_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr);
9559c7c4993SBarry Smith   }
9569c7c4993SBarry Smith 
9579c7c4993SBarry Smith   /* do sends:
9589c7c4993SBarry Smith       1) starts[i] gives the starting index in svalues for stuff going to
9599c7c4993SBarry Smith          the ith processor
9609c7c4993SBarry Smith   */
9619c7c4993SBarry Smith   ierr = PetscMalloc((N+1)*sizeof(PetscInt),&svalues);CHKERRQ(ierr);
9629c7c4993SBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
9639c7c4993SBarry Smith   ierr = PetscMalloc((size+1)*sizeof(PetscInt),&starts);CHKERRQ(ierr);
9649c7c4993SBarry Smith   starts[0] = 0;
9659c7c4993SBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + nprocs[2*i-2];}
9669c7c4993SBarry Smith   for (i=0; i<N; i++) {
9679c7c4993SBarry Smith     svalues[starts[owner[i]]++] = rows[i];
9689c7c4993SBarry Smith   }
9699c7c4993SBarry Smith 
9709c7c4993SBarry Smith   starts[0] = 0;
9719c7c4993SBarry Smith   for (i=1; i<size+1; i++) { starts[i] = starts[i-1] + nprocs[2*i-2];}
9729c7c4993SBarry Smith   count = 0;
9739c7c4993SBarry Smith   for (i=0; i<size; i++) {
9749c7c4993SBarry Smith     if (nprocs[2*i+1]) {
9759c7c4993SBarry Smith       ierr = MPI_Isend(svalues+starts[i],nprocs[2*i],MPIU_INT,i,tag,comm,send_waits+count++);CHKERRQ(ierr);
9769c7c4993SBarry Smith     }
9779c7c4993SBarry Smith   }
9789c7c4993SBarry Smith   ierr = PetscFree(starts);CHKERRQ(ierr);
9799c7c4993SBarry Smith 
9809c7c4993SBarry Smith   base = owners[rank];
9819c7c4993SBarry Smith 
9829c7c4993SBarry Smith   /*  wait on receives */
9839c7c4993SBarry Smith   ierr   = PetscMalloc2(nrecvs,PetscInt,&lens,nrecvs,PetscInt,&source);CHKERRQ(ierr);
9849c7c4993SBarry Smith   count  = nrecvs; slen = 0;
9859c7c4993SBarry Smith   while (count) {
9869c7c4993SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
9879c7c4993SBarry Smith     /* unpack receives into our local space */
9889c7c4993SBarry Smith     ierr = MPI_Get_count(&recv_status,MPIU_INT,&n);CHKERRQ(ierr);
9899c7c4993SBarry Smith     source[imdex]  = recv_status.MPI_SOURCE;
9909c7c4993SBarry Smith     lens[imdex]    = n;
9919c7c4993SBarry Smith     slen          += n;
9929c7c4993SBarry Smith     count--;
9939c7c4993SBarry Smith   }
9949c7c4993SBarry Smith   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
9959c7c4993SBarry Smith 
9969c7c4993SBarry Smith   /* move the data into the send scatter */
9979c7c4993SBarry Smith   ierr = PetscMalloc((slen+1)*sizeof(PetscInt),&lrows);CHKERRQ(ierr);
9989c7c4993SBarry Smith   count = 0;
9999c7c4993SBarry Smith   for (i=0; i<nrecvs; i++) {
10009c7c4993SBarry Smith     values = rvalues + i*nmax;
10019c7c4993SBarry Smith     for (j=0; j<lens[i]; j++) {
10029c7c4993SBarry Smith       lrows[count++] = values[j] - base;
10039c7c4993SBarry Smith     }
10049c7c4993SBarry Smith   }
10059c7c4993SBarry Smith   ierr = PetscFree(rvalues);CHKERRQ(ierr);
10069c7c4993SBarry Smith   ierr = PetscFree2(lens,source);CHKERRQ(ierr);
10079c7c4993SBarry Smith   ierr = PetscFree(owner);CHKERRQ(ierr);
10089c7c4993SBarry Smith   ierr = PetscFree(nprocs);CHKERRQ(ierr);
1009564f14d6SBarry Smith   /* lrows are the local rows to be zeroed, slen is the number of local rows */
10109c7c4993SBarry Smith 
1011564f14d6SBarry Smith   /* zero diagonal part of matrix */
1012564f14d6SBarry Smith   ierr = MatZeroRowsColumns(l->A,slen,lrows,diag,x,b);CHKERRQ(ierr);
10139c7c4993SBarry Smith 
1014564f14d6SBarry Smith   /* handle off diagonal part of matrix */
1015564f14d6SBarry Smith   ierr = MatGetVecs(A,&xmask,PETSC_NULL);CHKERRQ(ierr);
1016564f14d6SBarry Smith   ierr = VecDuplicate(l->lvec,&lmask);CHKERRQ(ierr);
1017564f14d6SBarry Smith   ierr = VecGetArray(xmask,&bb);CHKERRQ(ierr);
10189c7c4993SBarry Smith   for (i=0; i<slen; i++) {
1019564f14d6SBarry Smith     bb[lrows[i]] = 1;
10209c7c4993SBarry Smith   }
1021564f14d6SBarry Smith   ierr = VecRestoreArray(xmask,&bb);CHKERRQ(ierr);
1022564f14d6SBarry Smith   ierr = VecScatterBegin(l->Mvctx,xmask,lmask,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1023564f14d6SBarry Smith   ierr = VecScatterEnd(l->Mvctx,xmask,lmask,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10246bf464f9SBarry Smith   ierr = VecDestroy(&xmask);CHKERRQ(ierr);
1025377aa5a1SBarry Smith   if (x) {
1026564f14d6SBarry Smith     ierr = VecScatterBegin(l->Mvctx,x,l->lvec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1027564f14d6SBarry Smith     ierr = VecScatterEnd(l->Mvctx,x,l->lvec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1028564f14d6SBarry Smith     ierr = VecGetArrayRead(l->lvec,&xx);CHKERRQ(ierr);
1029564f14d6SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
1030377aa5a1SBarry Smith   }
1031377aa5a1SBarry Smith   ierr = VecGetArray(lmask,&mask);CHKERRQ(ierr);
1032564f14d6SBarry Smith 
1033564f14d6SBarry Smith   /* remove zeroed rows of off diagonal matrix */
1034564f14d6SBarry Smith   ii = aij->i;
1035564f14d6SBarry Smith   for (i=0; i<slen; i++) {
1036564f14d6SBarry Smith     ierr = PetscMemzero(aij->a + ii[lrows[i]],(ii[lrows[i]+1] - ii[lrows[i]])*sizeof(PetscScalar));CHKERRQ(ierr);
10379c7c4993SBarry Smith   }
1038564f14d6SBarry Smith 
1039564f14d6SBarry Smith   /* loop over all elements of off process part of matrix zeroing removed columns*/
1040564f14d6SBarry Smith   if (aij->compressedrow.use){
1041564f14d6SBarry Smith     m    = aij->compressedrow.nrows;
1042564f14d6SBarry Smith     ii   = aij->compressedrow.i;
1043564f14d6SBarry Smith     ridx = aij->compressedrow.rindex;
1044564f14d6SBarry Smith     for (i=0; i<m; i++){
1045564f14d6SBarry Smith       n   = ii[i+1] - ii[i];
1046564f14d6SBarry Smith       aj  = aij->j + ii[i];
1047564f14d6SBarry Smith       aa  = aij->a + ii[i];
1048564f14d6SBarry Smith 
1049564f14d6SBarry Smith       for (j=0; j<n; j++) {
105025266a92SSatish Balay         if (PetscAbsScalar(mask[*aj])) {
1051377aa5a1SBarry Smith           if (b) bb[*ridx] -= *aa*xx[*aj];
1052564f14d6SBarry Smith           *aa        = 0.0;
1053564f14d6SBarry Smith         }
1054564f14d6SBarry Smith         aa++;
1055564f14d6SBarry Smith         aj++;
1056564f14d6SBarry Smith       }
1057564f14d6SBarry Smith       ridx++;
1058564f14d6SBarry Smith     }
1059564f14d6SBarry Smith   } else { /* do not use compressed row format */
1060564f14d6SBarry Smith     m = l->B->rmap->n;
1061564f14d6SBarry Smith     for (i=0; i<m; i++) {
1062564f14d6SBarry Smith       n   = ii[i+1] - ii[i];
1063564f14d6SBarry Smith       aj  = aij->j + ii[i];
1064564f14d6SBarry Smith       aa  = aij->a + ii[i];
1065564f14d6SBarry Smith       for (j=0; j<n; j++) {
106625266a92SSatish Balay         if (PetscAbsScalar(mask[*aj])) {
1067377aa5a1SBarry Smith           if (b) bb[i] -= *aa*xx[*aj];
1068564f14d6SBarry Smith           *aa    = 0.0;
1069564f14d6SBarry Smith         }
1070564f14d6SBarry Smith         aa++;
1071564f14d6SBarry Smith         aj++;
1072564f14d6SBarry Smith       }
1073564f14d6SBarry Smith     }
1074564f14d6SBarry Smith   }
1075377aa5a1SBarry Smith   if (x) {
1076564f14d6SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
1077564f14d6SBarry Smith     ierr = VecRestoreArrayRead(l->lvec,&xx);CHKERRQ(ierr);
1078377aa5a1SBarry Smith   }
1079377aa5a1SBarry Smith   ierr = VecRestoreArray(lmask,&mask);CHKERRQ(ierr);
10806bf464f9SBarry Smith   ierr = VecDestroy(&lmask);CHKERRQ(ierr);
10819c7c4993SBarry Smith   ierr = PetscFree(lrows);CHKERRQ(ierr);
10829c7c4993SBarry Smith 
10839c7c4993SBarry Smith   /* wait on sends */
10849c7c4993SBarry Smith   if (nsends) {
10859c7c4993SBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
10869c7c4993SBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
10879c7c4993SBarry Smith     ierr = PetscFree(send_status);CHKERRQ(ierr);
10889c7c4993SBarry Smith   }
10899c7c4993SBarry Smith   ierr = PetscFree(send_waits);CHKERRQ(ierr);
10909c7c4993SBarry Smith   ierr = PetscFree(svalues);CHKERRQ(ierr);
10919c7c4993SBarry Smith 
10929c7c4993SBarry Smith   PetscFunctionReturn(0);
10939c7c4993SBarry Smith }
10949c7c4993SBarry Smith 
10959c7c4993SBarry Smith #undef __FUNCT__
10964a2ae208SSatish Balay #define __FUNCT__ "MatMult_MPIAIJ"
1097dfbe8321SBarry Smith PetscErrorCode MatMult_MPIAIJ(Mat A,Vec xx,Vec yy)
10981eb62cbbSBarry Smith {
1099416022c9SBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
1100dfbe8321SBarry Smith   PetscErrorCode ierr;
1101b1d57f15SBarry Smith   PetscInt       nt;
1102416022c9SBarry Smith 
11033a40ed3dSBarry Smith   PetscFunctionBegin;
1104a2ce50c7SBarry Smith   ierr = VecGetLocalSize(xx,&nt);CHKERRQ(ierr);
110565e19b50SBarry Smith   if (nt != A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Incompatible partition of A (%D) and xx (%D)",A->cmap->n,nt);
1106ca9f406cSSatish Balay   ierr = VecScatterBegin(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1107f830108cSBarry Smith   ierr = (*a->A->ops->mult)(a->A,xx,yy);CHKERRQ(ierr);
1108ca9f406cSSatish Balay   ierr = VecScatterEnd(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1109f830108cSBarry Smith   ierr = (*a->B->ops->multadd)(a->B,a->lvec,yy,yy);CHKERRQ(ierr);
11103a40ed3dSBarry Smith   PetscFunctionReturn(0);
11111eb62cbbSBarry Smith }
11121eb62cbbSBarry Smith 
11134a2ae208SSatish Balay #undef __FUNCT__
1114bd0c2dcbSBarry Smith #define __FUNCT__ "MatMultDiagonalBlock_MPIAIJ"
1115bd0c2dcbSBarry Smith PetscErrorCode MatMultDiagonalBlock_MPIAIJ(Mat A,Vec bb,Vec xx)
1116bd0c2dcbSBarry Smith {
1117bd0c2dcbSBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
1118bd0c2dcbSBarry Smith   PetscErrorCode ierr;
1119bd0c2dcbSBarry Smith 
1120bd0c2dcbSBarry Smith   PetscFunctionBegin;
1121bd0c2dcbSBarry Smith   ierr = MatMultDiagonalBlock(a->A,bb,xx);CHKERRQ(ierr);
1122bd0c2dcbSBarry Smith   PetscFunctionReturn(0);
1123bd0c2dcbSBarry Smith }
1124bd0c2dcbSBarry Smith 
1125bd0c2dcbSBarry Smith #undef __FUNCT__
11264a2ae208SSatish Balay #define __FUNCT__ "MatMultAdd_MPIAIJ"
1127dfbe8321SBarry Smith PetscErrorCode MatMultAdd_MPIAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1128da3a660dSBarry Smith {
1129416022c9SBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
1130dfbe8321SBarry Smith   PetscErrorCode ierr;
11313a40ed3dSBarry Smith 
11323a40ed3dSBarry Smith   PetscFunctionBegin;
1133ca9f406cSSatish Balay   ierr = VecScatterBegin(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1134f830108cSBarry Smith   ierr = (*a->A->ops->multadd)(a->A,xx,yy,zz);CHKERRQ(ierr);
1135ca9f406cSSatish Balay   ierr = VecScatterEnd(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1136f830108cSBarry Smith   ierr = (*a->B->ops->multadd)(a->B,a->lvec,zz,zz);CHKERRQ(ierr);
11373a40ed3dSBarry Smith   PetscFunctionReturn(0);
1138da3a660dSBarry Smith }
1139da3a660dSBarry Smith 
11404a2ae208SSatish Balay #undef __FUNCT__
11414a2ae208SSatish Balay #define __FUNCT__ "MatMultTranspose_MPIAIJ"
1142dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_MPIAIJ(Mat A,Vec xx,Vec yy)
1143da3a660dSBarry Smith {
1144416022c9SBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
1145dfbe8321SBarry Smith   PetscErrorCode ierr;
1146ace3abfcSBarry Smith   PetscBool      merged;
1147da3a660dSBarry Smith 
11483a40ed3dSBarry Smith   PetscFunctionBegin;
1149a5ff213dSBarry Smith   ierr = VecScatterGetMerged(a->Mvctx,&merged);CHKERRQ(ierr);
1150da3a660dSBarry Smith   /* do nondiagonal part */
11517c922b88SBarry Smith   ierr = (*a->B->ops->multtranspose)(a->B,xx,a->lvec);CHKERRQ(ierr);
1152a5ff213dSBarry Smith   if (!merged) {
1153da3a660dSBarry Smith     /* send it on its way */
1154ca9f406cSSatish Balay     ierr = VecScatterBegin(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1155da3a660dSBarry Smith     /* do local part */
11567c922b88SBarry Smith     ierr = (*a->A->ops->multtranspose)(a->A,xx,yy);CHKERRQ(ierr);
1157da3a660dSBarry Smith     /* receive remote parts: note this assumes the values are not actually */
1158a5ff213dSBarry Smith     /* added in yy until the next line, */
1159ca9f406cSSatish Balay     ierr = VecScatterEnd(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1160a5ff213dSBarry Smith   } else {
1161a5ff213dSBarry Smith     /* do local part */
1162a5ff213dSBarry Smith     ierr = (*a->A->ops->multtranspose)(a->A,xx,yy);CHKERRQ(ierr);
1163a5ff213dSBarry Smith     /* send it on its way */
1164ca9f406cSSatish Balay     ierr = VecScatterBegin(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1165a5ff213dSBarry Smith     /* values actually were received in the Begin() but we need to call this nop */
1166ca9f406cSSatish Balay     ierr = VecScatterEnd(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1167a5ff213dSBarry Smith   }
11683a40ed3dSBarry Smith   PetscFunctionReturn(0);
1169da3a660dSBarry Smith }
1170da3a660dSBarry Smith 
1171cd0d46ebSvictorle EXTERN_C_BEGIN
1172cd0d46ebSvictorle #undef __FUNCT__
11735fbd3699SBarry Smith #define __FUNCT__ "MatIsTranspose_MPIAIJ"
11747087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_MPIAIJ(Mat Amat,Mat Bmat,PetscReal tol,PetscBool  *f)
1175cd0d46ebSvictorle {
11764f423910Svictorle   MPI_Comm       comm;
1177cd0d46ebSvictorle   Mat_MPIAIJ     *Aij = (Mat_MPIAIJ *) Amat->data, *Bij;
117866501d38Svictorle   Mat            Adia = Aij->A, Bdia, Aoff,Boff,*Aoffs,*Boffs;
1179cd0d46ebSvictorle   IS             Me,Notme;
11806849ba73SBarry Smith   PetscErrorCode ierr;
1181b1d57f15SBarry Smith   PetscInt       M,N,first,last,*notme,i;
1182b1d57f15SBarry Smith   PetscMPIInt    size;
1183cd0d46ebSvictorle 
1184cd0d46ebSvictorle   PetscFunctionBegin;
118542e5f5b4Svictorle 
118642e5f5b4Svictorle   /* Easy test: symmetric diagonal block */
118766501d38Svictorle   Bij = (Mat_MPIAIJ *) Bmat->data; Bdia = Bij->A;
11885485867bSBarry Smith   ierr = MatIsTranspose(Adia,Bdia,tol,f);CHKERRQ(ierr);
1189cd0d46ebSvictorle   if (!*f) PetscFunctionReturn(0);
11904f423910Svictorle   ierr = PetscObjectGetComm((PetscObject)Amat,&comm);CHKERRQ(ierr);
1191b1d57f15SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1192b1d57f15SBarry Smith   if (size == 1) PetscFunctionReturn(0);
119342e5f5b4Svictorle 
119442e5f5b4Svictorle   /* Hard test: off-diagonal block. This takes a MatGetSubMatrix. */
1195cd0d46ebSvictorle   ierr = MatGetSize(Amat,&M,&N);CHKERRQ(ierr);
1196cd0d46ebSvictorle   ierr = MatGetOwnershipRange(Amat,&first,&last);CHKERRQ(ierr);
1197b1d57f15SBarry Smith   ierr = PetscMalloc((N-last+first)*sizeof(PetscInt),&notme);CHKERRQ(ierr);
1198cd0d46ebSvictorle   for (i=0; i<first; i++) notme[i] = i;
1199cd0d46ebSvictorle   for (i=last; i<M; i++) notme[i-last+first] = i;
120070b3c8c7SBarry Smith   ierr = ISCreateGeneral(MPI_COMM_SELF,N-last+first,notme,PETSC_COPY_VALUES,&Notme);CHKERRQ(ierr);
1201268466fbSBarry Smith   ierr = ISCreateStride(MPI_COMM_SELF,last-first,first,1,&Me);CHKERRQ(ierr);
1202268466fbSBarry Smith   ierr = MatGetSubMatrices(Amat,1,&Me,&Notme,MAT_INITIAL_MATRIX,&Aoffs);CHKERRQ(ierr);
120366501d38Svictorle   Aoff = Aoffs[0];
1204268466fbSBarry Smith   ierr = MatGetSubMatrices(Bmat,1,&Notme,&Me,MAT_INITIAL_MATRIX,&Boffs);CHKERRQ(ierr);
120566501d38Svictorle   Boff = Boffs[0];
12065485867bSBarry Smith   ierr = MatIsTranspose(Aoff,Boff,tol,f);CHKERRQ(ierr);
120766501d38Svictorle   ierr = MatDestroyMatrices(1,&Aoffs);CHKERRQ(ierr);
120866501d38Svictorle   ierr = MatDestroyMatrices(1,&Boffs);CHKERRQ(ierr);
12096bf464f9SBarry Smith   ierr = ISDestroy(&Me);CHKERRQ(ierr);
12106bf464f9SBarry Smith   ierr = ISDestroy(&Notme);CHKERRQ(ierr);
12113e0d0d19SHong Zhang   ierr = PetscFree(notme);CHKERRQ(ierr);
1212cd0d46ebSvictorle    PetscFunctionReturn(0);
1213cd0d46ebSvictorle }
1214cd0d46ebSvictorle EXTERN_C_END
1215cd0d46ebSvictorle 
12164a2ae208SSatish Balay #undef __FUNCT__
12174a2ae208SSatish Balay #define __FUNCT__ "MatMultTransposeAdd_MPIAIJ"
1218dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_MPIAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1219da3a660dSBarry Smith {
1220416022c9SBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
1221dfbe8321SBarry Smith   PetscErrorCode ierr;
1222da3a660dSBarry Smith 
12233a40ed3dSBarry Smith   PetscFunctionBegin;
1224da3a660dSBarry Smith   /* do nondiagonal part */
12257c922b88SBarry Smith   ierr = (*a->B->ops->multtranspose)(a->B,xx,a->lvec);CHKERRQ(ierr);
1226da3a660dSBarry Smith   /* send it on its way */
1227ca9f406cSSatish Balay   ierr = VecScatterBegin(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1228da3a660dSBarry Smith   /* do local part */
12297c922b88SBarry Smith   ierr = (*a->A->ops->multtransposeadd)(a->A,xx,yy,zz);CHKERRQ(ierr);
1230a5ff213dSBarry Smith   /* receive remote parts */
1231ca9f406cSSatish Balay   ierr = VecScatterEnd(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12323a40ed3dSBarry Smith   PetscFunctionReturn(0);
1233da3a660dSBarry Smith }
1234da3a660dSBarry Smith 
12351eb62cbbSBarry Smith /*
12361eb62cbbSBarry Smith   This only works correctly for square matrices where the subblock A->A is the
12371eb62cbbSBarry Smith    diagonal block
12381eb62cbbSBarry Smith */
12394a2ae208SSatish Balay #undef __FUNCT__
12404a2ae208SSatish Balay #define __FUNCT__ "MatGetDiagonal_MPIAIJ"
1241dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_MPIAIJ(Mat A,Vec v)
12421eb62cbbSBarry Smith {
1243dfbe8321SBarry Smith   PetscErrorCode ierr;
1244416022c9SBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
12453a40ed3dSBarry Smith 
12463a40ed3dSBarry Smith   PetscFunctionBegin;
1247e7e72b3dSBarry Smith   if (A->rmap->N != A->cmap->N) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Supports only square matrix where A->A is diag block");
1248e7e72b3dSBarry Smith   if (A->rmap->rstart != A->cmap->rstart || A->rmap->rend != A->cmap->rend) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"row partition must equal col partition");
12493a40ed3dSBarry Smith   ierr = MatGetDiagonal(a->A,v);CHKERRQ(ierr);
12503a40ed3dSBarry Smith   PetscFunctionReturn(0);
12511eb62cbbSBarry Smith }
12521eb62cbbSBarry Smith 
12534a2ae208SSatish Balay #undef __FUNCT__
12544a2ae208SSatish Balay #define __FUNCT__ "MatScale_MPIAIJ"
1255f4df32b1SMatthew Knepley PetscErrorCode MatScale_MPIAIJ(Mat A,PetscScalar aa)
1256052efed2SBarry Smith {
1257052efed2SBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
1258dfbe8321SBarry Smith   PetscErrorCode ierr;
12593a40ed3dSBarry Smith 
12603a40ed3dSBarry Smith   PetscFunctionBegin;
1261f4df32b1SMatthew Knepley   ierr = MatScale(a->A,aa);CHKERRQ(ierr);
1262f4df32b1SMatthew Knepley   ierr = MatScale(a->B,aa);CHKERRQ(ierr);
12633a40ed3dSBarry Smith   PetscFunctionReturn(0);
1264052efed2SBarry Smith }
1265052efed2SBarry Smith 
12664a2ae208SSatish Balay #undef __FUNCT__
12674a2ae208SSatish Balay #define __FUNCT__ "MatDestroy_MPIAIJ"
1268dfbe8321SBarry Smith PetscErrorCode MatDestroy_MPIAIJ(Mat mat)
12691eb62cbbSBarry Smith {
127044a69424SLois Curfman McInnes   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)mat->data;
1271dfbe8321SBarry Smith   PetscErrorCode ierr;
127283e2fdc7SBarry Smith 
12733a40ed3dSBarry Smith   PetscFunctionBegin;
1274aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1275d0f46423SBarry Smith   PetscLogObjectState((PetscObject)mat,"Rows=%D, Cols=%D",mat->rmap->N,mat->cmap->N);
1276a5a9c739SBarry Smith #endif
12778798bf22SSatish Balay   ierr = MatStashDestroy_Private(&mat->stash);CHKERRQ(ierr);
12786bf464f9SBarry Smith   ierr = VecDestroy(&aij->diag);CHKERRQ(ierr);
12796bf464f9SBarry Smith   ierr = MatDestroy(&aij->A);CHKERRQ(ierr);
12806bf464f9SBarry Smith   ierr = MatDestroy(&aij->B);CHKERRQ(ierr);
1281aa482453SBarry Smith #if defined (PETSC_USE_CTABLE)
12826bc0bbbfSBarry Smith   ierr = PetscTableDestroy(&aij->colmap);CHKERRQ(ierr);
1283b1fc9764SSatish Balay #else
128405b42c5fSBarry Smith   ierr = PetscFree(aij->colmap);CHKERRQ(ierr);
1285b1fc9764SSatish Balay #endif
128605b42c5fSBarry Smith   ierr = PetscFree(aij->garray);CHKERRQ(ierr);
12876bf464f9SBarry Smith   ierr = VecDestroy(&aij->lvec);CHKERRQ(ierr);
12886bf464f9SBarry Smith   ierr = VecScatterDestroy(&aij->Mvctx);CHKERRQ(ierr);
128903095fedSBarry Smith   ierr = PetscFree2(aij->rowvalues,aij->rowindices);CHKERRQ(ierr);
12908aa348c1SBarry Smith   ierr = PetscFree(aij->ld);CHKERRQ(ierr);
1291bf0cc555SLisandro Dalcin   ierr = PetscFree(mat->data);CHKERRQ(ierr);
1292901853e0SKris Buschelman 
1293dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)mat,0);CHKERRQ(ierr);
1294901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatStoreValues_C","",PETSC_NULL);CHKERRQ(ierr);
1295901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatRetrieveValues_C","",PETSC_NULL);CHKERRQ(ierr);
1296901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatGetDiagonalBlock_C","",PETSC_NULL);CHKERRQ(ierr);
1297901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatIsTranspose_C","",PETSC_NULL);CHKERRQ(ierr);
1298901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIAIJSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr);
1299ff69c46cSKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIAIJSetPreallocationCSR_C","",PETSC_NULL);CHKERRQ(ierr);
1300901853e0SKris Buschelman   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDiagonalScaleLocal_C","",PETSC_NULL);CHKERRQ(ierr);
1301471cc821SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpiaij_mpisbaij_C","",PETSC_NULL);CHKERRQ(ierr);
13023a40ed3dSBarry Smith   PetscFunctionReturn(0);
13031eb62cbbSBarry Smith }
1304ee50ffe9SBarry Smith 
13054a2ae208SSatish Balay #undef __FUNCT__
13068e2fed03SBarry Smith #define __FUNCT__ "MatView_MPIAIJ_Binary"
1307dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ_Binary(Mat mat,PetscViewer viewer)
13088e2fed03SBarry Smith {
13098e2fed03SBarry Smith   Mat_MPIAIJ        *aij = (Mat_MPIAIJ*)mat->data;
13108e2fed03SBarry Smith   Mat_SeqAIJ*       A = (Mat_SeqAIJ*)aij->A->data;
13118e2fed03SBarry Smith   Mat_SeqAIJ*       B = (Mat_SeqAIJ*)aij->B->data;
13126849ba73SBarry Smith   PetscErrorCode    ierr;
131332dcc486SBarry Smith   PetscMPIInt       rank,size,tag = ((PetscObject)viewer)->tag;
13146f69ff64SBarry Smith   int               fd;
1315a788621eSSatish Balay   PetscInt          nz,header[4],*row_lengths,*range=0,rlen,i;
1316d0f46423SBarry Smith   PetscInt          nzmax,*column_indices,j,k,col,*garray = aij->garray,cnt,cstart = mat->cmap->rstart,rnz;
13178e2fed03SBarry Smith   PetscScalar       *column_values;
131885ebf7a4SBarry Smith   PetscInt          message_count,flowcontrolcount;
1319b37d52dbSMark F. Adams   FILE              *file;
13208e2fed03SBarry Smith 
13218e2fed03SBarry Smith   PetscFunctionBegin;
13227adad957SLisandro Dalcin   ierr = MPI_Comm_rank(((PetscObject)mat)->comm,&rank);CHKERRQ(ierr);
13237adad957SLisandro Dalcin   ierr = MPI_Comm_size(((PetscObject)mat)->comm,&size);CHKERRQ(ierr);
13248e2fed03SBarry Smith   nz   = A->nz + B->nz;
1325958c9bccSBarry Smith   if (!rank) {
13260700a824SBarry Smith     header[0] = MAT_FILE_CLASSID;
1327d0f46423SBarry Smith     header[1] = mat->rmap->N;
1328d0f46423SBarry Smith     header[2] = mat->cmap->N;
13297adad957SLisandro Dalcin     ierr = MPI_Reduce(&nz,&header[3],1,MPIU_INT,MPI_SUM,0,((PetscObject)mat)->comm);CHKERRQ(ierr);
13308e2fed03SBarry Smith     ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
13316f69ff64SBarry Smith     ierr = PetscBinaryWrite(fd,header,4,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
13328e2fed03SBarry Smith     /* get largest number of rows any processor has */
1333d0f46423SBarry Smith     rlen = mat->rmap->n;
1334d0f46423SBarry Smith     range = mat->rmap->range;
13358e2fed03SBarry Smith     for (i=1; i<size; i++) {
13368e2fed03SBarry Smith       rlen = PetscMax(rlen,range[i+1] - range[i]);
13378e2fed03SBarry Smith     }
13388e2fed03SBarry Smith   } else {
13397adad957SLisandro Dalcin     ierr = MPI_Reduce(&nz,0,1,MPIU_INT,MPI_SUM,0,((PetscObject)mat)->comm);CHKERRQ(ierr);
1340d0f46423SBarry Smith     rlen = mat->rmap->n;
13418e2fed03SBarry Smith   }
13428e2fed03SBarry Smith 
13438e2fed03SBarry Smith   /* load up the local row counts */
1344b1d57f15SBarry Smith   ierr = PetscMalloc((rlen+1)*sizeof(PetscInt),&row_lengths);CHKERRQ(ierr);
1345d0f46423SBarry Smith   for (i=0; i<mat->rmap->n; i++) {
13468e2fed03SBarry Smith     row_lengths[i] = A->i[i+1] - A->i[i] + B->i[i+1] - B->i[i];
13478e2fed03SBarry Smith   }
13488e2fed03SBarry Smith 
13498e2fed03SBarry Smith   /* store the row lengths to the file */
135085ebf7a4SBarry Smith   ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr);
1351958c9bccSBarry Smith   if (!rank) {
1352d0f46423SBarry Smith     ierr = PetscBinaryWrite(fd,row_lengths,mat->rmap->n,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
13538e2fed03SBarry Smith     for (i=1; i<size; i++) {
135485ebf7a4SBarry Smith       ierr = PetscViewerFlowControlStepMaster(viewer,i,message_count,flowcontrolcount);CHKERRQ(ierr);
13558e2fed03SBarry Smith       rlen = range[i+1] - range[i];
1356a25532f0SBarry Smith       ierr = MPIULong_Recv(row_lengths,rlen,MPIU_INT,i,tag,((PetscObject)mat)->comm);CHKERRQ(ierr);
13576f69ff64SBarry Smith       ierr = PetscBinaryWrite(fd,row_lengths,rlen,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
13588e2fed03SBarry Smith     }
135985ebf7a4SBarry Smith     ierr = PetscViewerFlowControlEndMaster(viewer,message_count);CHKERRQ(ierr);
13608e2fed03SBarry Smith   } else {
136185ebf7a4SBarry Smith     ierr = PetscViewerFlowControlStepWorker(viewer,rank,message_count);CHKERRQ(ierr);
1362a25532f0SBarry Smith     ierr = MPIULong_Send(row_lengths,mat->rmap->n,MPIU_INT,0,tag,((PetscObject)mat)->comm);CHKERRQ(ierr);
136385ebf7a4SBarry Smith     ierr = PetscViewerFlowControlEndWorker(viewer,message_count);CHKERRQ(ierr);
13648e2fed03SBarry Smith   }
13658e2fed03SBarry Smith   ierr = PetscFree(row_lengths);CHKERRQ(ierr);
13668e2fed03SBarry Smith 
13678e2fed03SBarry Smith   /* load up the local column indices */
13688e2fed03SBarry Smith   nzmax = nz; /* )th processor needs space a largest processor needs */
13697adad957SLisandro Dalcin   ierr = MPI_Reduce(&nz,&nzmax,1,MPIU_INT,MPI_MAX,0,((PetscObject)mat)->comm);CHKERRQ(ierr);
1370b1d57f15SBarry Smith   ierr = PetscMalloc((nzmax+1)*sizeof(PetscInt),&column_indices);CHKERRQ(ierr);
13718e2fed03SBarry Smith   cnt  = 0;
1372d0f46423SBarry Smith   for (i=0; i<mat->rmap->n; i++) {
13738e2fed03SBarry Smith     for (j=B->i[i]; j<B->i[i+1]; j++) {
13748e2fed03SBarry Smith       if ( (col = garray[B->j[j]]) > cstart) break;
13758e2fed03SBarry Smith       column_indices[cnt++] = col;
13768e2fed03SBarry Smith     }
13778e2fed03SBarry Smith     for (k=A->i[i]; k<A->i[i+1]; k++) {
13788e2fed03SBarry Smith       column_indices[cnt++] = A->j[k] + cstart;
13798e2fed03SBarry Smith     }
13808e2fed03SBarry Smith     for (; j<B->i[i+1]; j++) {
13818e2fed03SBarry Smith       column_indices[cnt++] = garray[B->j[j]];
13828e2fed03SBarry Smith     }
13838e2fed03SBarry Smith   }
1384e32f2f54SBarry Smith   if (cnt != A->nz + B->nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Internal PETSc error: cnt = %D nz = %D",cnt,A->nz+B->nz);
13858e2fed03SBarry Smith 
13868e2fed03SBarry Smith   /* store the column indices to the file */
138785ebf7a4SBarry Smith    ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr);
1388958c9bccSBarry Smith   if (!rank) {
13898e2fed03SBarry Smith     MPI_Status status;
13906f69ff64SBarry Smith     ierr = PetscBinaryWrite(fd,column_indices,nz,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
13918e2fed03SBarry Smith     for (i=1; i<size; i++) {
139285ebf7a4SBarry Smith       ierr = PetscViewerFlowControlStepMaster(viewer,i,message_count,flowcontrolcount);CHKERRQ(ierr);
13937adad957SLisandro Dalcin       ierr = MPI_Recv(&rnz,1,MPIU_INT,i,tag,((PetscObject)mat)->comm,&status);CHKERRQ(ierr);
1394e32f2f54SBarry Smith       if (rnz > nzmax) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Internal PETSc error: nz = %D nzmax = %D",nz,nzmax);
1395a25532f0SBarry Smith       ierr = MPIULong_Recv(column_indices,rnz,MPIU_INT,i,tag,((PetscObject)mat)->comm);CHKERRQ(ierr);
13966f69ff64SBarry Smith       ierr = PetscBinaryWrite(fd,column_indices,rnz,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
13978e2fed03SBarry Smith     }
139885ebf7a4SBarry Smith      ierr = PetscViewerFlowControlEndMaster(viewer,message_count);CHKERRQ(ierr);
13998e2fed03SBarry Smith   } else {
140085ebf7a4SBarry Smith     ierr = PetscViewerFlowControlStepWorker(viewer,rank,message_count);CHKERRQ(ierr);
14017adad957SLisandro Dalcin     ierr = MPI_Send(&nz,1,MPIU_INT,0,tag,((PetscObject)mat)->comm);CHKERRQ(ierr);
1402a25532f0SBarry Smith     ierr = MPIULong_Send(column_indices,nz,MPIU_INT,0,tag,((PetscObject)mat)->comm);CHKERRQ(ierr);
140385ebf7a4SBarry Smith     ierr = PetscViewerFlowControlEndWorker(viewer,message_count);CHKERRQ(ierr);
14048e2fed03SBarry Smith   }
14058e2fed03SBarry Smith   ierr = PetscFree(column_indices);CHKERRQ(ierr);
14068e2fed03SBarry Smith 
14078e2fed03SBarry Smith   /* load up the local column values */
14088e2fed03SBarry Smith   ierr = PetscMalloc((nzmax+1)*sizeof(PetscScalar),&column_values);CHKERRQ(ierr);
14098e2fed03SBarry Smith   cnt  = 0;
1410d0f46423SBarry Smith   for (i=0; i<mat->rmap->n; i++) {
14118e2fed03SBarry Smith     for (j=B->i[i]; j<B->i[i+1]; j++) {
14128e2fed03SBarry Smith       if ( garray[B->j[j]] > cstart) break;
14138e2fed03SBarry Smith       column_values[cnt++] = B->a[j];
14148e2fed03SBarry Smith     }
14158e2fed03SBarry Smith     for (k=A->i[i]; k<A->i[i+1]; k++) {
14168e2fed03SBarry Smith       column_values[cnt++] = A->a[k];
14178e2fed03SBarry Smith     }
14188e2fed03SBarry Smith     for (; j<B->i[i+1]; j++) {
14198e2fed03SBarry Smith       column_values[cnt++] = B->a[j];
14208e2fed03SBarry Smith     }
14218e2fed03SBarry Smith   }
1422e32f2f54SBarry Smith   if (cnt != A->nz + B->nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Internal PETSc error: cnt = %D nz = %D",cnt,A->nz+B->nz);
14238e2fed03SBarry Smith 
14248e2fed03SBarry Smith   /* store the column values to the file */
142585ebf7a4SBarry Smith    ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr);
1426958c9bccSBarry Smith   if (!rank) {
14278e2fed03SBarry Smith     MPI_Status status;
14286f69ff64SBarry Smith     ierr = PetscBinaryWrite(fd,column_values,nz,PETSC_SCALAR,PETSC_TRUE);CHKERRQ(ierr);
14298e2fed03SBarry Smith     for (i=1; i<size; i++) {
143085ebf7a4SBarry Smith        ierr = PetscViewerFlowControlStepMaster(viewer,i,message_count,flowcontrolcount);CHKERRQ(ierr);
14317adad957SLisandro Dalcin       ierr = MPI_Recv(&rnz,1,MPIU_INT,i,tag,((PetscObject)mat)->comm,&status);CHKERRQ(ierr);
1432e32f2f54SBarry Smith       if (rnz > nzmax) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Internal PETSc error: nz = %D nzmax = %D",nz,nzmax);
1433a25532f0SBarry Smith       ierr = MPIULong_Recv(column_values,rnz,MPIU_SCALAR,i,tag,((PetscObject)mat)->comm);CHKERRQ(ierr);
14346f69ff64SBarry Smith       ierr = PetscBinaryWrite(fd,column_values,rnz,PETSC_SCALAR,PETSC_TRUE);CHKERRQ(ierr);
14358e2fed03SBarry Smith     }
143685ebf7a4SBarry Smith     ierr = PetscViewerFlowControlEndMaster(viewer,message_count);CHKERRQ(ierr);
14378e2fed03SBarry Smith   } else {
143885ebf7a4SBarry Smith     ierr = PetscViewerFlowControlStepWorker(viewer,rank,message_count);CHKERRQ(ierr);
14397adad957SLisandro Dalcin     ierr = MPI_Send(&nz,1,MPIU_INT,0,tag,((PetscObject)mat)->comm);CHKERRQ(ierr);
1440a25532f0SBarry Smith     ierr = MPIULong_Send(column_values,nz,MPIU_SCALAR,0,tag,((PetscObject)mat)->comm);CHKERRQ(ierr);
144185ebf7a4SBarry Smith     ierr = PetscViewerFlowControlEndWorker(viewer,message_count);CHKERRQ(ierr);
14428e2fed03SBarry Smith   }
14438e2fed03SBarry Smith   ierr = PetscFree(column_values);CHKERRQ(ierr);
1444b37d52dbSMark F. Adams 
1445b37d52dbSMark F. Adams   ierr = PetscViewerBinaryGetInfoPointer(viewer,&file);CHKERRQ(ierr);
1446b37d52dbSMark F. Adams   if (file) {
1447b37d52dbSMark F. Adams     fprintf(file,"-matload_block_size %d\n",(int)mat->rmap->bs);
1448b37d52dbSMark F. Adams   }
1449b37d52dbSMark F. Adams 
14508e2fed03SBarry Smith   PetscFunctionReturn(0);
14518e2fed03SBarry Smith }
14528e2fed03SBarry Smith 
14538e2fed03SBarry Smith #undef __FUNCT__
14544a2ae208SSatish Balay #define __FUNCT__ "MatView_MPIAIJ_ASCIIorDraworSocket"
1455dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ_ASCIIorDraworSocket(Mat mat,PetscViewer viewer)
1456416022c9SBarry Smith {
145744a69424SLois Curfman McInnes   Mat_MPIAIJ        *aij = (Mat_MPIAIJ*)mat->data;
1458dfbe8321SBarry Smith   PetscErrorCode    ierr;
145932dcc486SBarry Smith   PetscMPIInt       rank = aij->rank,size = aij->size;
1460ace3abfcSBarry Smith   PetscBool         isdraw,iascii,isbinary;
1461b0a32e0cSBarry Smith   PetscViewer       sviewer;
1462f3ef73ceSBarry Smith   PetscViewerFormat format;
1463416022c9SBarry Smith 
14643a40ed3dSBarry Smith   PetscFunctionBegin;
1465251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1466251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1467251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
146832077d6dSBarry Smith   if (iascii) {
1469b0a32e0cSBarry Smith     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1470456192e2SBarry Smith     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
14714e220ebcSLois Curfman McInnes       MatInfo    info;
1472ace3abfcSBarry Smith       PetscBool  inodes;
1473923f20ffSKris Buschelman 
14747adad957SLisandro Dalcin       ierr = MPI_Comm_rank(((PetscObject)mat)->comm,&rank);CHKERRQ(ierr);
1475888f2ed8SSatish Balay       ierr = MatGetInfo(mat,MAT_LOCAL,&info);CHKERRQ(ierr);
1476923f20ffSKris Buschelman       ierr = MatInodeGetInodeSizes(aij->A,PETSC_NULL,(PetscInt **)&inodes,PETSC_NULL);CHKERRQ(ierr);
14777b23a99aSBarry Smith       ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
1478923f20ffSKris Buschelman       if (!inodes) {
147977431f27SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %D nz %D nz alloced %D mem %D, not using I-node routines\n",
1480d0f46423SBarry Smith 					      rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr);
14816831982aSBarry Smith       } else {
148277431f27SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %D nz %D nz alloced %D mem %D, using I-node routines\n",
1483d0f46423SBarry Smith 		    rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr);
14846831982aSBarry Smith       }
1485888f2ed8SSatish Balay       ierr = MatGetInfo(aij->A,MAT_LOCAL,&info);CHKERRQ(ierr);
148677431f27SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] on-diagonal part: nz %D \n",rank,(PetscInt)info.nz_used);CHKERRQ(ierr);
1487888f2ed8SSatish Balay       ierr = MatGetInfo(aij->B,MAT_LOCAL,&info);CHKERRQ(ierr);
148877431f27SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] off-diagonal part: nz %D \n",rank,(PetscInt)info.nz_used);CHKERRQ(ierr);
1489b0a32e0cSBarry Smith       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14907b23a99aSBarry Smith       ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
149107d81ca4SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"Information on VecScatter used in matrix-vector product: \n");CHKERRQ(ierr);
1492a40aa06bSLois Curfman McInnes       ierr = VecScatterView(aij->Mvctx,viewer);CHKERRQ(ierr);
14933a40ed3dSBarry Smith       PetscFunctionReturn(0);
1494fb9695e5SSatish Balay     } else if (format == PETSC_VIEWER_ASCII_INFO) {
1495923f20ffSKris Buschelman       PetscInt   inodecount,inodelimit,*inodes;
1496923f20ffSKris Buschelman       ierr = MatInodeGetInodeSizes(aij->A,&inodecount,&inodes,&inodelimit);CHKERRQ(ierr);
1497923f20ffSKris Buschelman       if (inodes) {
1498923f20ffSKris Buschelman         ierr = PetscViewerASCIIPrintf(viewer,"using I-node (on process 0) routines: found %D nodes, limit used is %D\n",inodecount,inodelimit);CHKERRQ(ierr);
1499d38fa0fbSBarry Smith       } else {
1500d38fa0fbSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"not using I-node (on process 0) routines\n");CHKERRQ(ierr);
1501d38fa0fbSBarry Smith       }
15023a40ed3dSBarry Smith       PetscFunctionReturn(0);
15034aedb280SBarry Smith     } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
15044aedb280SBarry Smith       PetscFunctionReturn(0);
150508480c60SBarry Smith     }
15068e2fed03SBarry Smith   } else if (isbinary) {
15078e2fed03SBarry Smith     if (size == 1) {
15087adad957SLisandro Dalcin       ierr = PetscObjectSetName((PetscObject)aij->A,((PetscObject)mat)->name);CHKERRQ(ierr);
15098e2fed03SBarry Smith       ierr = MatView(aij->A,viewer);CHKERRQ(ierr);
15108e2fed03SBarry Smith     } else {
15118e2fed03SBarry Smith       ierr = MatView_MPIAIJ_Binary(mat,viewer);CHKERRQ(ierr);
15128e2fed03SBarry Smith     }
15138e2fed03SBarry Smith     PetscFunctionReturn(0);
15140f5bd95cSBarry Smith   } else if (isdraw) {
1515b0a32e0cSBarry Smith     PetscDraw  draw;
1516ace3abfcSBarry Smith     PetscBool  isnull;
1517b0a32e0cSBarry Smith     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1518b0a32e0cSBarry Smith     ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
151919bcc07fSBarry Smith   }
152019bcc07fSBarry Smith 
152117699dbbSLois Curfman McInnes   if (size == 1) {
15227adad957SLisandro Dalcin     ierr = PetscObjectSetName((PetscObject)aij->A,((PetscObject)mat)->name);CHKERRQ(ierr);
152378b31e54SBarry Smith     ierr = MatView(aij->A,viewer);CHKERRQ(ierr);
15243a40ed3dSBarry Smith   } else {
152595373324SBarry Smith     /* assemble the entire matrix onto first processor. */
152695373324SBarry Smith     Mat         A;
1527ec8511deSBarry Smith     Mat_SeqAIJ  *Aloc;
1528d0f46423SBarry Smith     PetscInt    M = mat->rmap->N,N = mat->cmap->N,m,*ai,*aj,row,*cols,i,*ct;
1529dd6ea824SBarry Smith     MatScalar   *a;
15302ee70a88SLois Curfman McInnes 
153132a366e4SMatthew Knepley     if (mat->rmap->N > 1024) {
1532ace3abfcSBarry Smith       PetscBool  flg = PETSC_FALSE;
153332a366e4SMatthew Knepley 
1534acfcf0e5SJed Brown       ierr = PetscOptionsGetBool(((PetscObject) mat)->prefix, "-mat_ascii_output_large", &flg,PETSC_NULL);CHKERRQ(ierr);
153532a366e4SMatthew Knepley       if (!flg) {
1536e7e72b3dSBarry Smith         SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_ARG_OUTOFRANGE,"ASCII matrix output not allowed for matrices with more than 1024 rows, use binary format instead.\nYou can override this restriction using -mat_ascii_output_large.");
153732a366e4SMatthew Knepley       }
153832a366e4SMatthew Knepley     }
15390805154bSBarry Smith 
15407adad957SLisandro Dalcin     ierr = MatCreate(((PetscObject)mat)->comm,&A);CHKERRQ(ierr);
154117699dbbSLois Curfman McInnes     if (!rank) {
1542f69a0ea3SMatthew Knepley       ierr = MatSetSizes(A,M,N,M,N);CHKERRQ(ierr);
15433a40ed3dSBarry Smith     } else {
1544f69a0ea3SMatthew Knepley       ierr = MatSetSizes(A,0,0,M,N);CHKERRQ(ierr);
154595373324SBarry Smith     }
1546f204ca49SKris Buschelman     /* This is just a temporary matrix, so explicitly using MATMPIAIJ is probably best */
1547f204ca49SKris Buschelman     ierr = MatSetType(A,MATMPIAIJ);CHKERRQ(ierr);
1548f204ca49SKris Buschelman     ierr = MatMPIAIJSetPreallocation(A,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
15492b82e772SSatish Balay     ierr = MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
155052e6d16bSBarry Smith     ierr = PetscLogObjectParent(mat,A);CHKERRQ(ierr);
1551416022c9SBarry Smith 
155295373324SBarry Smith     /* copy over the A part */
1553ec8511deSBarry Smith     Aloc = (Mat_SeqAIJ*)aij->A->data;
1554d0f46423SBarry Smith     m = aij->A->rmap->n; ai = Aloc->i; aj = Aloc->j; a = Aloc->a;
1555d0f46423SBarry Smith     row = mat->rmap->rstart;
1556d0f46423SBarry Smith     for (i=0; i<ai[m]; i++) {aj[i] += mat->cmap->rstart ;}
155795373324SBarry Smith     for (i=0; i<m; i++) {
1558416022c9SBarry Smith       ierr = MatSetValues(A,1,&row,ai[i+1]-ai[i],aj,a,INSERT_VALUES);CHKERRQ(ierr);
155995373324SBarry Smith       row++; a += ai[i+1]-ai[i]; aj += ai[i+1]-ai[i];
156095373324SBarry Smith     }
15612ee70a88SLois Curfman McInnes     aj = Aloc->j;
1562d0f46423SBarry Smith     for (i=0; i<ai[m]; i++) {aj[i] -= mat->cmap->rstart;}
156395373324SBarry Smith 
156495373324SBarry Smith     /* copy over the B part */
1565ec8511deSBarry Smith     Aloc = (Mat_SeqAIJ*)aij->B->data;
1566d0f46423SBarry Smith     m    = aij->B->rmap->n;  ai = Aloc->i; aj = Aloc->j; a = Aloc->a;
1567d0f46423SBarry Smith     row  = mat->rmap->rstart;
1568b1d57f15SBarry Smith     ierr = PetscMalloc((ai[m]+1)*sizeof(PetscInt),&cols);CHKERRQ(ierr);
1569b0a32e0cSBarry Smith     ct   = cols;
1570bfec09a0SHong Zhang     for (i=0; i<ai[m]; i++) {cols[i] = aij->garray[aj[i]];}
157195373324SBarry Smith     for (i=0; i<m; i++) {
1572416022c9SBarry Smith       ierr = MatSetValues(A,1,&row,ai[i+1]-ai[i],cols,a,INSERT_VALUES);CHKERRQ(ierr);
157395373324SBarry Smith       row++; a += ai[i+1]-ai[i]; cols += ai[i+1]-ai[i];
157495373324SBarry Smith     }
1575606d414cSSatish Balay     ierr = PetscFree(ct);CHKERRQ(ierr);
15766d4a8577SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15776d4a8577SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
157855843e3eSBarry Smith     /*
157955843e3eSBarry Smith        Everyone has to call to draw the matrix since the graphics waits are
1580b0a32e0cSBarry Smith        synchronized across all processors that share the PetscDraw object
158155843e3eSBarry Smith     */
1582b0a32e0cSBarry Smith     ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr);
1583e03a110bSBarry Smith     if (!rank) {
15847adad957SLisandro Dalcin       ierr = PetscObjectSetName((PetscObject)((Mat_MPIAIJ*)(A->data))->A,((PetscObject)mat)->name);CHKERRQ(ierr);
15857566de4bSShri Abhyankar       /* Set the type name to MATMPIAIJ so that the correct type can be printed out by PetscObjectPrintClassNamePrefixType() in MatView_SeqAIJ_ASCII()*/
15867566de4bSShri Abhyankar       PetscStrcpy(((PetscObject)((Mat_MPIAIJ*)(A->data))->A)->type_name,MATMPIAIJ);
15876831982aSBarry Smith       ierr = MatView(((Mat_MPIAIJ*)(A->data))->A,sviewer);CHKERRQ(ierr);
158895373324SBarry Smith     }
1589b0a32e0cSBarry Smith     ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr);
15906bf464f9SBarry Smith     ierr = MatDestroy(&A);CHKERRQ(ierr);
159195373324SBarry Smith   }
15923a40ed3dSBarry Smith   PetscFunctionReturn(0);
15931eb62cbbSBarry Smith }
15941eb62cbbSBarry Smith 
15954a2ae208SSatish Balay #undef __FUNCT__
15964a2ae208SSatish Balay #define __FUNCT__ "MatView_MPIAIJ"
1597dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ(Mat mat,PetscViewer viewer)
1598416022c9SBarry Smith {
1599dfbe8321SBarry Smith   PetscErrorCode ierr;
1600ace3abfcSBarry Smith   PetscBool      iascii,isdraw,issocket,isbinary;
1601416022c9SBarry Smith 
16023a40ed3dSBarry Smith   PetscFunctionBegin;
1603251f4c67SDmitry Karpeev   ierr  = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1604251f4c67SDmitry Karpeev   ierr  = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1605251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1606251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSOCKET,&issocket);CHKERRQ(ierr);
160732077d6dSBarry Smith   if (iascii || isdraw || isbinary || issocket) {
16087b2a1423SBarry Smith     ierr = MatView_MPIAIJ_ASCIIorDraworSocket(mat,viewer);CHKERRQ(ierr);
16095cd90555SBarry Smith   } else {
1610e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by MPIAIJ matrices",((PetscObject)viewer)->type_name);
1611416022c9SBarry Smith   }
16123a40ed3dSBarry Smith   PetscFunctionReturn(0);
1613416022c9SBarry Smith }
1614416022c9SBarry Smith 
16154a2ae208SSatish Balay #undef __FUNCT__
161641f059aeSBarry Smith #define __FUNCT__ "MatSOR_MPIAIJ"
161741f059aeSBarry Smith PetscErrorCode MatSOR_MPIAIJ(Mat matin,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
16188a729477SBarry Smith {
161944a69424SLois Curfman McInnes   Mat_MPIAIJ     *mat = (Mat_MPIAIJ*)matin->data;
1620dfbe8321SBarry Smith   PetscErrorCode ierr;
16216987fefcSBarry Smith   Vec            bb1 = 0;
1622ace3abfcSBarry Smith   PetscBool      hasop;
16238a729477SBarry Smith 
16243a40ed3dSBarry Smith   PetscFunctionBegin;
162585911e72SJed Brown   if (its > 1 || ~flag & SOR_ZERO_INITIAL_GUESS || flag & SOR_EISENSTAT) {
162685911e72SJed Brown     ierr = VecDuplicate(bb,&bb1);CHKERRQ(ierr);
162785911e72SJed Brown   }
16282798e883SHong Zhang 
1629a2b30743SBarry Smith   if (flag == SOR_APPLY_UPPER) {
163041f059aeSBarry Smith     ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr);
1631a2b30743SBarry Smith     PetscFunctionReturn(0);
1632a2b30743SBarry Smith   }
1633a2b30743SBarry Smith 
1634c16cb8f2SBarry Smith   if ((flag & SOR_LOCAL_SYMMETRIC_SWEEP) == SOR_LOCAL_SYMMETRIC_SWEEP){
1635da3a660dSBarry Smith     if (flag & SOR_ZERO_INITIAL_GUESS) {
163641f059aeSBarry Smith       ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr);
16372798e883SHong Zhang       its--;
1638da3a660dSBarry Smith     }
16392798e883SHong Zhang 
16402798e883SHong Zhang     while (its--) {
1641ca9f406cSSatish Balay       ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1642ca9f406cSSatish Balay       ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16432798e883SHong Zhang 
1644c14dc6b6SHong Zhang       /* update rhs: bb1 = bb - B*x */
1645efb30889SBarry Smith       ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr);
1646c14dc6b6SHong Zhang       ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr);
16472798e883SHong Zhang 
1648c14dc6b6SHong Zhang       /* local sweep */
164941f059aeSBarry Smith       ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_SYMMETRIC_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr);
16502798e883SHong Zhang     }
16513a40ed3dSBarry Smith   } else if (flag & SOR_LOCAL_FORWARD_SWEEP){
1652da3a660dSBarry Smith     if (flag & SOR_ZERO_INITIAL_GUESS) {
165341f059aeSBarry Smith       ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr);
16542798e883SHong Zhang       its--;
1655da3a660dSBarry Smith     }
16562798e883SHong Zhang     while (its--) {
1657ca9f406cSSatish Balay       ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1658ca9f406cSSatish Balay       ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16592798e883SHong Zhang 
1660c14dc6b6SHong Zhang       /* update rhs: bb1 = bb - B*x */
1661efb30889SBarry Smith       ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr);
1662c14dc6b6SHong Zhang       ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr);
1663c14dc6b6SHong Zhang 
1664c14dc6b6SHong Zhang       /* local sweep */
166541f059aeSBarry Smith       ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_FORWARD_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr);
16662798e883SHong Zhang     }
16673a40ed3dSBarry Smith   } else if (flag & SOR_LOCAL_BACKWARD_SWEEP){
1668da3a660dSBarry Smith     if (flag & SOR_ZERO_INITIAL_GUESS) {
166941f059aeSBarry Smith       ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr);
16702798e883SHong Zhang       its--;
1671da3a660dSBarry Smith     }
16722798e883SHong Zhang     while (its--) {
1673ca9f406cSSatish Balay       ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1674ca9f406cSSatish Balay       ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16752798e883SHong Zhang 
1676c14dc6b6SHong Zhang       /* update rhs: bb1 = bb - B*x */
1677efb30889SBarry Smith       ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr);
1678c14dc6b6SHong Zhang       ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr);
16792798e883SHong Zhang 
1680c14dc6b6SHong Zhang       /* local sweep */
168141f059aeSBarry Smith       ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_BACKWARD_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr);
16822798e883SHong Zhang     }
1683a7420bb7SBarry Smith   }  else if (flag & SOR_EISENSTAT) {
1684a7420bb7SBarry Smith     Vec         xx1;
1685a7420bb7SBarry Smith 
1686a7420bb7SBarry Smith     ierr = VecDuplicate(bb,&xx1);CHKERRQ(ierr);
168741f059aeSBarry Smith     ierr = (*mat->A->ops->sor)(mat->A,bb,omega,(MatSORType)(SOR_ZERO_INITIAL_GUESS | SOR_LOCAL_BACKWARD_SWEEP),fshift,lits,1,xx);CHKERRQ(ierr);
1688a7420bb7SBarry Smith 
1689a7420bb7SBarry Smith     ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1690a7420bb7SBarry Smith     ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1691a7420bb7SBarry Smith     if (!mat->diag) {
1692a7420bb7SBarry Smith       ierr = MatGetVecs(matin,&mat->diag,PETSC_NULL);CHKERRQ(ierr);
1693a7420bb7SBarry Smith       ierr = MatGetDiagonal(matin,mat->diag);CHKERRQ(ierr);
1694a7420bb7SBarry Smith     }
1695bd0c2dcbSBarry Smith     ierr = MatHasOperation(matin,MATOP_MULT_DIAGONAL_BLOCK,&hasop);CHKERRQ(ierr);
1696bd0c2dcbSBarry Smith     if (hasop) {
1697bd0c2dcbSBarry Smith       ierr = MatMultDiagonalBlock(matin,xx,bb1);CHKERRQ(ierr);
1698bd0c2dcbSBarry Smith     } else {
1699a7420bb7SBarry Smith       ierr = VecPointwiseMult(bb1,mat->diag,xx);CHKERRQ(ierr);
1700bd0c2dcbSBarry Smith     }
1701887ee2caSBarry Smith     ierr = VecAYPX(bb1,(omega-2.0)/omega,bb);CHKERRQ(ierr);
1702887ee2caSBarry Smith 
1703a7420bb7SBarry Smith     ierr = MatMultAdd(mat->B,mat->lvec,bb1,bb1);CHKERRQ(ierr);
1704a7420bb7SBarry Smith 
1705a7420bb7SBarry Smith     /* local sweep */
170641f059aeSBarry Smith     ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,(MatSORType)(SOR_ZERO_INITIAL_GUESS | SOR_LOCAL_FORWARD_SWEEP),fshift,lits,1,xx1);CHKERRQ(ierr);
1707a7420bb7SBarry Smith     ierr = VecAXPY(xx,1.0,xx1);CHKERRQ(ierr);
17086bf464f9SBarry Smith     ierr = VecDestroy(&xx1);CHKERRQ(ierr);
170944b1af1bSBarry Smith   } else SETERRQ(((PetscObject)matin)->comm,PETSC_ERR_SUP,"Parallel SOR not supported");
1710c14dc6b6SHong Zhang 
17116bf464f9SBarry Smith   ierr = VecDestroy(&bb1);CHKERRQ(ierr);
17123a40ed3dSBarry Smith   PetscFunctionReturn(0);
17138a729477SBarry Smith }
1714a66be287SLois Curfman McInnes 
17154a2ae208SSatish Balay #undef __FUNCT__
171642e855d1Svictor #define __FUNCT__ "MatPermute_MPIAIJ"
171742e855d1Svictor PetscErrorCode MatPermute_MPIAIJ(Mat A,IS rowp,IS colp,Mat *B)
171842e855d1Svictor {
171923f569faSJed Brown   MPI_Comm       comm;
172023f569faSJed Brown   PetscInt       first,local_rowsize,local_colsize;
17215d0c19d7SBarry Smith   const PetscInt *rows;
172242e855d1Svictor   IS             crowp,growp,irowp,lrowp,lcolp,icolp;
172342e855d1Svictor   PetscErrorCode ierr;
172442e855d1Svictor 
172542e855d1Svictor   PetscFunctionBegin;
172642e855d1Svictor   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
172723f569faSJed Brown   /* make a collective version of 'rowp', this is to be tolerant of users who pass serial index sets */
172823f569faSJed Brown   ierr = ISOnComm(rowp,comm,PETSC_USE_POINTER,&crowp);CHKERRQ(ierr);
172942e855d1Svictor   /* collect the global row permutation and invert it */
173042e855d1Svictor   ierr = ISAllGather(crowp,&growp);CHKERRQ(ierr);
173142e855d1Svictor   ierr = ISSetPermutation(growp);CHKERRQ(ierr);
17326bf464f9SBarry Smith   ierr = ISDestroy(&crowp);CHKERRQ(ierr);
173342e855d1Svictor   ierr = ISInvertPermutation(growp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
173423f569faSJed Brown   ierr = ISDestroy(&growp);CHKERRQ(ierr);
173542e855d1Svictor   /* get the local target indices */
173642e855d1Svictor   ierr = MatGetOwnershipRange(A,&first,PETSC_NULL);CHKERRQ(ierr);
173723f569faSJed Brown   ierr = MatGetLocalSize(A,&local_rowsize,&local_colsize);CHKERRQ(ierr);
173842e855d1Svictor   ierr = ISGetIndices(irowp,&rows);CHKERRQ(ierr);
173923f569faSJed Brown   ierr = ISCreateGeneral(PETSC_COMM_SELF,local_rowsize,rows+first,PETSC_COPY_VALUES,&lrowp);CHKERRQ(ierr);
174042e855d1Svictor   ierr = ISRestoreIndices(irowp,&rows);CHKERRQ(ierr);
17416bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
174242e855d1Svictor   /* the column permutation is so much easier;
174342e855d1Svictor      make a local version of 'colp' and invert it */
174423f569faSJed Brown   ierr = ISOnComm(colp,PETSC_COMM_SELF,PETSC_USE_POINTER,&lcolp);CHKERRQ(ierr);
1745dbf0e21dSBarry Smith   ierr = ISSetPermutation(lcolp);CHKERRQ(ierr);
174642e855d1Svictor   ierr = ISInvertPermutation(lcolp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
17476bf464f9SBarry Smith   ierr = ISDestroy(&lcolp);CHKERRQ(ierr);
174842e855d1Svictor   /* now we just get the submatrix */
174923f569faSJed Brown   ierr = MatGetSubMatrix_MPIAIJ_Private(A,lrowp,icolp,local_colsize,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
175042e855d1Svictor   /* clean up */
17516bf464f9SBarry Smith   ierr = ISDestroy(&lrowp);CHKERRQ(ierr);
17526bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
175342e855d1Svictor   PetscFunctionReturn(0);
175442e855d1Svictor }
175542e855d1Svictor 
175642e855d1Svictor #undef __FUNCT__
17574a2ae208SSatish Balay #define __FUNCT__ "MatGetInfo_MPIAIJ"
1758dfbe8321SBarry Smith PetscErrorCode MatGetInfo_MPIAIJ(Mat matin,MatInfoType flag,MatInfo *info)
1759a66be287SLois Curfman McInnes {
1760a66be287SLois Curfman McInnes   Mat_MPIAIJ     *mat = (Mat_MPIAIJ*)matin->data;
1761a66be287SLois Curfman McInnes   Mat            A = mat->A,B = mat->B;
1762dfbe8321SBarry Smith   PetscErrorCode ierr;
1763329f5518SBarry Smith   PetscReal      isend[5],irecv[5];
1764a66be287SLois Curfman McInnes 
17653a40ed3dSBarry Smith   PetscFunctionBegin;
17664e220ebcSLois Curfman McInnes   info->block_size     = 1.0;
17674e220ebcSLois Curfman McInnes   ierr = MatGetInfo(A,MAT_LOCAL,info);CHKERRQ(ierr);
17684e220ebcSLois Curfman McInnes   isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded;
17694e220ebcSLois Curfman McInnes   isend[3] = info->memory;  isend[4] = info->mallocs;
17704e220ebcSLois Curfman McInnes   ierr = MatGetInfo(B,MAT_LOCAL,info);CHKERRQ(ierr);
17714e220ebcSLois Curfman McInnes   isend[0] += info->nz_used; isend[1] += info->nz_allocated; isend[2] += info->nz_unneeded;
17724e220ebcSLois Curfman McInnes   isend[3] += info->memory;  isend[4] += info->mallocs;
1773a66be287SLois Curfman McInnes   if (flag == MAT_LOCAL) {
17744e220ebcSLois Curfman McInnes     info->nz_used      = isend[0];
17754e220ebcSLois Curfman McInnes     info->nz_allocated = isend[1];
17764e220ebcSLois Curfman McInnes     info->nz_unneeded  = isend[2];
17774e220ebcSLois Curfman McInnes     info->memory       = isend[3];
17784e220ebcSLois Curfman McInnes     info->mallocs      = isend[4];
1779a66be287SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_MAX) {
1780d9822059SBarry Smith     ierr = MPI_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,((PetscObject)matin)->comm);CHKERRQ(ierr);
17814e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
17824e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
17834e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
17844e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
17854e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
1786a66be287SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_SUM) {
1787d9822059SBarry Smith     ierr = MPI_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,((PetscObject)matin)->comm);CHKERRQ(ierr);
17884e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
17894e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
17904e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
17914e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
17924e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
1793a66be287SLois Curfman McInnes   }
17944e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0; /* no parallel LU/ILU/Cholesky */
17954e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
17964e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
17973a40ed3dSBarry Smith   PetscFunctionReturn(0);
1798a66be287SLois Curfman McInnes }
1799a66be287SLois Curfman McInnes 
18004a2ae208SSatish Balay #undef __FUNCT__
18014a2ae208SSatish Balay #define __FUNCT__ "MatSetOption_MPIAIJ"
1802ace3abfcSBarry Smith PetscErrorCode MatSetOption_MPIAIJ(Mat A,MatOption op,PetscBool  flg)
1803c74985f6SBarry Smith {
1804c0bbcb79SLois Curfman McInnes   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
1805dfbe8321SBarry Smith   PetscErrorCode ierr;
1806c74985f6SBarry Smith 
18073a40ed3dSBarry Smith   PetscFunctionBegin;
180812c028f9SKris Buschelman   switch (op) {
1809512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
181012c028f9SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
181128b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
1812a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
181312c028f9SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
181412c028f9SKris Buschelman   case MAT_USE_INODES:
181512c028f9SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
1816fa1f0d2cSMatthew G Knepley     MatCheckPreallocated(A,1);
18174e0d8c25SBarry Smith     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
18184e0d8c25SBarry Smith     ierr = MatSetOption(a->B,op,flg);CHKERRQ(ierr);
181912c028f9SKris Buschelman     break;
182012c028f9SKris Buschelman   case MAT_ROW_ORIENTED:
18214e0d8c25SBarry Smith     a->roworiented = flg;
18224e0d8c25SBarry Smith     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
18234e0d8c25SBarry Smith     ierr = MatSetOption(a->B,op,flg);CHKERRQ(ierr);
182412c028f9SKris Buschelman     break;
18254e0d8c25SBarry Smith   case MAT_NEW_DIAGONALS:
1826290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
182712c028f9SKris Buschelman     break;
182812c028f9SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
18295c0f0b64SBarry Smith     a->donotstash = flg;
183012c028f9SKris Buschelman     break;
1831ffa07934SHong Zhang   case MAT_SPD:
1832ffa07934SHong Zhang     A->spd_set                         = PETSC_TRUE;
1833ffa07934SHong Zhang     A->spd                             = flg;
1834ffa07934SHong Zhang     if (flg) {
1835ffa07934SHong Zhang       A->symmetric                     = PETSC_TRUE;
1836ffa07934SHong Zhang       A->structurally_symmetric        = PETSC_TRUE;
1837ffa07934SHong Zhang       A->symmetric_set                 = PETSC_TRUE;
1838ffa07934SHong Zhang       A->structurally_symmetric_set    = PETSC_TRUE;
1839ffa07934SHong Zhang     }
1840ffa07934SHong Zhang     break;
184177e54ba9SKris Buschelman   case MAT_SYMMETRIC:
18424e0d8c25SBarry Smith     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
184325f421beSHong Zhang     break;
184477e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
1845eeffb40dSHong Zhang     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
1846eeffb40dSHong Zhang     break;
1847bf108f30SBarry Smith   case MAT_HERMITIAN:
1848eeffb40dSHong Zhang     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
1849eeffb40dSHong Zhang     break;
1850bf108f30SBarry Smith   case MAT_SYMMETRY_ETERNAL:
18514e0d8c25SBarry Smith     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
185277e54ba9SKris Buschelman     break;
185312c028f9SKris Buschelman   default:
1854e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
18553a40ed3dSBarry Smith   }
18563a40ed3dSBarry Smith   PetscFunctionReturn(0);
1857c74985f6SBarry Smith }
1858c74985f6SBarry Smith 
18594a2ae208SSatish Balay #undef __FUNCT__
18604a2ae208SSatish Balay #define __FUNCT__ "MatGetRow_MPIAIJ"
1861b1d57f15SBarry Smith PetscErrorCode MatGetRow_MPIAIJ(Mat matin,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
186239e00950SLois Curfman McInnes {
1863154123eaSLois Curfman McInnes   Mat_MPIAIJ     *mat = (Mat_MPIAIJ*)matin->data;
186487828ca2SBarry Smith   PetscScalar    *vworkA,*vworkB,**pvA,**pvB,*v_p;
18656849ba73SBarry Smith   PetscErrorCode ierr;
1866d0f46423SBarry Smith   PetscInt       i,*cworkA,*cworkB,**pcA,**pcB,cstart = matin->cmap->rstart;
1867d0f46423SBarry Smith   PetscInt       nztot,nzA,nzB,lrow,rstart = matin->rmap->rstart,rend = matin->rmap->rend;
1868b1d57f15SBarry Smith   PetscInt       *cmap,*idx_p;
186939e00950SLois Curfman McInnes 
18703a40ed3dSBarry Smith   PetscFunctionBegin;
1871e32f2f54SBarry Smith   if (mat->getrowactive) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Already active");
18727a0afa10SBarry Smith   mat->getrowactive = PETSC_TRUE;
18737a0afa10SBarry Smith 
187470f0671dSBarry Smith   if (!mat->rowvalues && (idx || v)) {
18757a0afa10SBarry Smith     /*
18767a0afa10SBarry Smith         allocate enough space to hold information from the longest row.
18777a0afa10SBarry Smith     */
18787a0afa10SBarry Smith     Mat_SeqAIJ *Aa = (Mat_SeqAIJ*)mat->A->data,*Ba = (Mat_SeqAIJ*)mat->B->data;
1879b1d57f15SBarry Smith     PetscInt   max = 1,tmp;
1880d0f46423SBarry Smith     for (i=0; i<matin->rmap->n; i++) {
18817a0afa10SBarry Smith       tmp = Aa->i[i+1] - Aa->i[i] + Ba->i[i+1] - Ba->i[i];
18827a0afa10SBarry Smith       if (max < tmp) { max = tmp; }
18837a0afa10SBarry Smith     }
18841d79065fSBarry Smith     ierr = PetscMalloc2(max,PetscScalar,&mat->rowvalues,max,PetscInt,&mat->rowindices);CHKERRQ(ierr);
18857a0afa10SBarry Smith   }
18867a0afa10SBarry Smith 
1887e7e72b3dSBarry Smith   if (row < rstart || row >= rend) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only local rows");
1888abc0e9e4SLois Curfman McInnes   lrow = row - rstart;
188939e00950SLois Curfman McInnes 
1890154123eaSLois Curfman McInnes   pvA = &vworkA; pcA = &cworkA; pvB = &vworkB; pcB = &cworkB;
1891154123eaSLois Curfman McInnes   if (!v)   {pvA = 0; pvB = 0;}
1892154123eaSLois Curfman McInnes   if (!idx) {pcA = 0; if (!v) pcB = 0;}
1893f830108cSBarry Smith   ierr = (*mat->A->ops->getrow)(mat->A,lrow,&nzA,pcA,pvA);CHKERRQ(ierr);
1894f830108cSBarry Smith   ierr = (*mat->B->ops->getrow)(mat->B,lrow,&nzB,pcB,pvB);CHKERRQ(ierr);
1895154123eaSLois Curfman McInnes   nztot = nzA + nzB;
1896154123eaSLois Curfman McInnes 
189770f0671dSBarry Smith   cmap  = mat->garray;
1898154123eaSLois Curfman McInnes   if (v  || idx) {
1899154123eaSLois Curfman McInnes     if (nztot) {
1900154123eaSLois Curfman McInnes       /* Sort by increasing column numbers, assuming A and B already sorted */
1901b1d57f15SBarry Smith       PetscInt imark = -1;
1902154123eaSLois Curfman McInnes       if (v) {
190370f0671dSBarry Smith         *v = v_p = mat->rowvalues;
190439e00950SLois Curfman McInnes         for (i=0; i<nzB; i++) {
190570f0671dSBarry Smith           if (cmap[cworkB[i]] < cstart)   v_p[i] = vworkB[i];
1906154123eaSLois Curfman McInnes           else break;
1907154123eaSLois Curfman McInnes         }
1908154123eaSLois Curfman McInnes         imark = i;
190970f0671dSBarry Smith         for (i=0; i<nzA; i++)     v_p[imark+i] = vworkA[i];
191070f0671dSBarry Smith         for (i=imark; i<nzB; i++) v_p[nzA+i]   = vworkB[i];
1911154123eaSLois Curfman McInnes       }
1912154123eaSLois Curfman McInnes       if (idx) {
191370f0671dSBarry Smith         *idx = idx_p = mat->rowindices;
191470f0671dSBarry Smith         if (imark > -1) {
191570f0671dSBarry Smith           for (i=0; i<imark; i++) {
191670f0671dSBarry Smith             idx_p[i] = cmap[cworkB[i]];
191770f0671dSBarry Smith           }
191870f0671dSBarry Smith         } else {
1919154123eaSLois Curfman McInnes           for (i=0; i<nzB; i++) {
192070f0671dSBarry Smith             if (cmap[cworkB[i]] < cstart)   idx_p[i] = cmap[cworkB[i]];
1921154123eaSLois Curfman McInnes             else break;
1922154123eaSLois Curfman McInnes           }
1923154123eaSLois Curfman McInnes           imark = i;
192470f0671dSBarry Smith         }
192570f0671dSBarry Smith         for (i=0; i<nzA; i++)     idx_p[imark+i] = cstart + cworkA[i];
192670f0671dSBarry Smith         for (i=imark; i<nzB; i++) idx_p[nzA+i]   = cmap[cworkB[i]];
192739e00950SLois Curfman McInnes       }
19283f97c4b0SBarry Smith     } else {
19291ca473b0SSatish Balay       if (idx) *idx = 0;
19301ca473b0SSatish Balay       if (v)   *v   = 0;
19311ca473b0SSatish Balay     }
1932154123eaSLois Curfman McInnes   }
193339e00950SLois Curfman McInnes   *nz = nztot;
1934f830108cSBarry Smith   ierr = (*mat->A->ops->restorerow)(mat->A,lrow,&nzA,pcA,pvA);CHKERRQ(ierr);
1935f830108cSBarry Smith   ierr = (*mat->B->ops->restorerow)(mat->B,lrow,&nzB,pcB,pvB);CHKERRQ(ierr);
19363a40ed3dSBarry Smith   PetscFunctionReturn(0);
193739e00950SLois Curfman McInnes }
193839e00950SLois Curfman McInnes 
19394a2ae208SSatish Balay #undef __FUNCT__
19404a2ae208SSatish Balay #define __FUNCT__ "MatRestoreRow_MPIAIJ"
1941b1d57f15SBarry Smith PetscErrorCode MatRestoreRow_MPIAIJ(Mat mat,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
194239e00950SLois Curfman McInnes {
19437a0afa10SBarry Smith   Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data;
19443a40ed3dSBarry Smith 
19453a40ed3dSBarry Smith   PetscFunctionBegin;
1946e7e72b3dSBarry Smith   if (!aij->getrowactive) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"MatGetRow() must be called first");
19477a0afa10SBarry Smith   aij->getrowactive = PETSC_FALSE;
19483a40ed3dSBarry Smith   PetscFunctionReturn(0);
194939e00950SLois Curfman McInnes }
195039e00950SLois Curfman McInnes 
19514a2ae208SSatish Balay #undef __FUNCT__
19524a2ae208SSatish Balay #define __FUNCT__ "MatNorm_MPIAIJ"
1953dfbe8321SBarry Smith PetscErrorCode MatNorm_MPIAIJ(Mat mat,NormType type,PetscReal *norm)
1954855ac2c5SLois Curfman McInnes {
1955855ac2c5SLois Curfman McInnes   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)mat->data;
1956ec8511deSBarry Smith   Mat_SeqAIJ     *amat = (Mat_SeqAIJ*)aij->A->data,*bmat = (Mat_SeqAIJ*)aij->B->data;
1957dfbe8321SBarry Smith   PetscErrorCode ierr;
1958d0f46423SBarry Smith   PetscInt       i,j,cstart = mat->cmap->rstart;
1959329f5518SBarry Smith   PetscReal      sum = 0.0;
1960a77337e4SBarry Smith   MatScalar      *v;
196104ca555eSLois Curfman McInnes 
19623a40ed3dSBarry Smith   PetscFunctionBegin;
196317699dbbSLois Curfman McInnes   if (aij->size == 1) {
196414183eadSLois Curfman McInnes     ierr =  MatNorm(aij->A,type,norm);CHKERRQ(ierr);
196537fa93a5SLois Curfman McInnes   } else {
196604ca555eSLois Curfman McInnes     if (type == NORM_FROBENIUS) {
196704ca555eSLois Curfman McInnes       v = amat->a;
196804ca555eSLois Curfman McInnes       for (i=0; i<amat->nz; i++) {
1969aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
1970329f5518SBarry Smith         sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
197104ca555eSLois Curfman McInnes #else
197204ca555eSLois Curfman McInnes         sum += (*v)*(*v); v++;
197304ca555eSLois Curfman McInnes #endif
197404ca555eSLois Curfman McInnes       }
197504ca555eSLois Curfman McInnes       v = bmat->a;
197604ca555eSLois Curfman McInnes       for (i=0; i<bmat->nz; i++) {
1977aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
1978329f5518SBarry Smith         sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
197904ca555eSLois Curfman McInnes #else
198004ca555eSLois Curfman McInnes         sum += (*v)*(*v); v++;
198104ca555eSLois Curfman McInnes #endif
198204ca555eSLois Curfman McInnes       }
1983d9822059SBarry Smith       ierr = MPI_Allreduce(&sum,norm,1,MPIU_REAL,MPIU_SUM,((PetscObject)mat)->comm);CHKERRQ(ierr);
19848f1a2a5eSBarry Smith       *norm = PetscSqrtReal(*norm);
19853a40ed3dSBarry Smith     } else if (type == NORM_1) { /* max column norm */
1986329f5518SBarry Smith       PetscReal *tmp,*tmp2;
1987b1d57f15SBarry Smith       PetscInt  *jj,*garray = aij->garray;
1988d0f46423SBarry Smith       ierr = PetscMalloc((mat->cmap->N+1)*sizeof(PetscReal),&tmp);CHKERRQ(ierr);
1989d0f46423SBarry Smith       ierr = PetscMalloc((mat->cmap->N+1)*sizeof(PetscReal),&tmp2);CHKERRQ(ierr);
1990d0f46423SBarry Smith       ierr = PetscMemzero(tmp,mat->cmap->N*sizeof(PetscReal));CHKERRQ(ierr);
199104ca555eSLois Curfman McInnes       *norm = 0.0;
199204ca555eSLois Curfman McInnes       v = amat->a; jj = amat->j;
199304ca555eSLois Curfman McInnes       for (j=0; j<amat->nz; j++) {
1994bfec09a0SHong Zhang         tmp[cstart + *jj++ ] += PetscAbsScalar(*v);  v++;
199504ca555eSLois Curfman McInnes       }
199604ca555eSLois Curfman McInnes       v = bmat->a; jj = bmat->j;
199704ca555eSLois Curfman McInnes       for (j=0; j<bmat->nz; j++) {
1998bfec09a0SHong Zhang         tmp[garray[*jj++]] += PetscAbsScalar(*v); v++;
199904ca555eSLois Curfman McInnes       }
2000d9822059SBarry Smith       ierr = MPI_Allreduce(tmp,tmp2,mat->cmap->N,MPIU_REAL,MPIU_SUM,((PetscObject)mat)->comm);CHKERRQ(ierr);
2001d0f46423SBarry Smith       for (j=0; j<mat->cmap->N; j++) {
200204ca555eSLois Curfman McInnes         if (tmp2[j] > *norm) *norm = tmp2[j];
200304ca555eSLois Curfman McInnes       }
2004606d414cSSatish Balay       ierr = PetscFree(tmp);CHKERRQ(ierr);
2005606d414cSSatish Balay       ierr = PetscFree(tmp2);CHKERRQ(ierr);
20063a40ed3dSBarry Smith     } else if (type == NORM_INFINITY) { /* max row norm */
2007329f5518SBarry Smith       PetscReal ntemp = 0.0;
2008d0f46423SBarry Smith       for (j=0; j<aij->A->rmap->n; j++) {
2009bfec09a0SHong Zhang         v = amat->a + amat->i[j];
201004ca555eSLois Curfman McInnes         sum = 0.0;
201104ca555eSLois Curfman McInnes         for (i=0; i<amat->i[j+1]-amat->i[j]; i++) {
2012cddf8d76SBarry Smith           sum += PetscAbsScalar(*v); v++;
201304ca555eSLois Curfman McInnes         }
2014bfec09a0SHong Zhang         v = bmat->a + bmat->i[j];
201504ca555eSLois Curfman McInnes         for (i=0; i<bmat->i[j+1]-bmat->i[j]; i++) {
2016cddf8d76SBarry Smith           sum += PetscAbsScalar(*v); v++;
201704ca555eSLois Curfman McInnes         }
2018515d9167SLois Curfman McInnes         if (sum > ntemp) ntemp = sum;
201904ca555eSLois Curfman McInnes       }
2020d9822059SBarry Smith       ierr = MPI_Allreduce(&ntemp,norm,1,MPIU_REAL,MPIU_MAX,((PetscObject)mat)->comm);CHKERRQ(ierr);
2021ca161407SBarry Smith     } else {
2022e7e72b3dSBarry Smith       SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_SUP,"No support for two norm");
202304ca555eSLois Curfman McInnes     }
202437fa93a5SLois Curfman McInnes   }
20253a40ed3dSBarry Smith   PetscFunctionReturn(0);
2026855ac2c5SLois Curfman McInnes }
2027855ac2c5SLois Curfman McInnes 
20284a2ae208SSatish Balay #undef __FUNCT__
20294a2ae208SSatish Balay #define __FUNCT__ "MatTranspose_MPIAIJ"
2030fc4dec0aSBarry Smith PetscErrorCode MatTranspose_MPIAIJ(Mat A,MatReuse reuse,Mat *matout)
2031b7c46309SBarry Smith {
2032b7c46309SBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
2033da668accSHong Zhang   Mat_SeqAIJ     *Aloc=(Mat_SeqAIJ*)a->A->data,*Bloc=(Mat_SeqAIJ*)a->B->data;
2034dfbe8321SBarry Smith   PetscErrorCode ierr;
2035d0f46423SBarry Smith   PetscInt       M = A->rmap->N,N = A->cmap->N,ma,na,mb,*ai,*aj,*bi,*bj,row,*cols,*cols_tmp,i,*d_nnz;
2036d0f46423SBarry Smith   PetscInt       cstart=A->cmap->rstart,ncol;
20373a40ed3dSBarry Smith   Mat            B;
2038a77337e4SBarry Smith   MatScalar      *array;
2039b7c46309SBarry Smith 
20403a40ed3dSBarry Smith   PetscFunctionBegin;
2041e7e72b3dSBarry Smith   if (reuse == MAT_REUSE_MATRIX && A == *matout && M != N) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_SIZ,"Square matrix only for in-place");
2042da668accSHong Zhang 
2043d0f46423SBarry Smith   ma = A->rmap->n; na = A->cmap->n; mb = a->B->rmap->n;
2044da668accSHong Zhang   ai = Aloc->i; aj = Aloc->j;
2045da668accSHong Zhang   bi = Bloc->i; bj = Bloc->j;
2046fc73b1b3SBarry Smith   if (reuse == MAT_INITIAL_MATRIX || *matout == A) {
2047fc73b1b3SBarry Smith     /* compute d_nnz for preallocation; o_nnz is approximated by d_nnz to avoid communication */
2048fc73b1b3SBarry Smith     ierr = PetscMalloc((1+na)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr);
2049da668accSHong Zhang     ierr = PetscMemzero(d_nnz,(1+na)*sizeof(PetscInt));CHKERRQ(ierr);
2050da668accSHong Zhang     for (i=0; i<ai[ma]; i++){
2051da668accSHong Zhang       d_nnz[aj[i]] ++;
2052da668accSHong Zhang       aj[i] += cstart; /* global col index to be used by MatSetValues() */
2053d4bb536fSBarry Smith     }
2054d4bb536fSBarry Smith 
20557adad957SLisandro Dalcin     ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
2056d0f46423SBarry Smith     ierr = MatSetSizes(B,A->cmap->n,A->rmap->n,N,M);CHKERRQ(ierr);
2057a2f3521dSMark F. Adams     ierr = MatSetBlockSizes(B,A->cmap->bs,A->rmap->bs); CHKERRQ(ierr);
20587adad957SLisandro Dalcin     ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2059da668accSHong Zhang     ierr = MatMPIAIJSetPreallocation(B,0,d_nnz,0,d_nnz);CHKERRQ(ierr);
20601d567fd6SHong Zhang     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
2061fc73b1b3SBarry Smith     ierr = PetscFree(d_nnz);CHKERRQ(ierr);
2062fc4dec0aSBarry Smith   } else {
2063fc4dec0aSBarry Smith     B = *matout;
20646ffab4bbSHong Zhang     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
20656ffab4bbSHong Zhang     for (i=0; i<ai[ma]; i++){
20666ffab4bbSHong Zhang       aj[i] += cstart; /* global col index to be used by MatSetValues() */
20676ffab4bbSHong Zhang     }
2068fc4dec0aSBarry Smith   }
2069b7c46309SBarry Smith 
2070b7c46309SBarry Smith   /* copy over the A part */
2071da668accSHong Zhang   array = Aloc->a;
2072d0f46423SBarry Smith   row = A->rmap->rstart;
2073da668accSHong Zhang   for (i=0; i<ma; i++) {
2074da668accSHong Zhang     ncol = ai[i+1]-ai[i];
2075da668accSHong Zhang     ierr = MatSetValues(B,ncol,aj,1,&row,array,INSERT_VALUES);CHKERRQ(ierr);
2076da668accSHong Zhang     row++; array += ncol; aj += ncol;
2077b7c46309SBarry Smith   }
2078b7c46309SBarry Smith   aj = Aloc->j;
2079da668accSHong Zhang   for (i=0; i<ai[ma]; i++) aj[i] -= cstart; /* resume local col index */
2080b7c46309SBarry Smith 
2081b7c46309SBarry Smith   /* copy over the B part */
2082fc73b1b3SBarry Smith   ierr = PetscMalloc(bi[mb]*sizeof(PetscInt),&cols);CHKERRQ(ierr);
2083fc73b1b3SBarry Smith   ierr = PetscMemzero(cols,bi[mb]*sizeof(PetscInt));CHKERRQ(ierr);
2084da668accSHong Zhang   array = Bloc->a;
2085d0f46423SBarry Smith   row = A->rmap->rstart;
2086da668accSHong Zhang   for (i=0; i<bi[mb]; i++) {cols[i] = a->garray[bj[i]];}
208761a2fbbaSHong Zhang   cols_tmp = cols;
2088da668accSHong Zhang   for (i=0; i<mb; i++) {
2089da668accSHong Zhang     ncol = bi[i+1]-bi[i];
209061a2fbbaSHong Zhang     ierr = MatSetValues(B,ncol,cols_tmp,1,&row,array,INSERT_VALUES);CHKERRQ(ierr);
209161a2fbbaSHong Zhang     row++; array += ncol; cols_tmp += ncol;
2092b7c46309SBarry Smith   }
2093fc73b1b3SBarry Smith   ierr = PetscFree(cols);CHKERRQ(ierr);
2094fc73b1b3SBarry Smith 
20956d4a8577SBarry Smith   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20966d4a8577SBarry Smith   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2097815cbec1SBarry Smith   if (reuse == MAT_INITIAL_MATRIX || *matout != A) {
20980de55854SLois Curfman McInnes     *matout = B;
20990de55854SLois Curfman McInnes   } else {
2100eb6b5d47SBarry Smith     ierr = MatHeaderMerge(A,B);CHKERRQ(ierr);
21010de55854SLois Curfman McInnes   }
21023a40ed3dSBarry Smith   PetscFunctionReturn(0);
2103b7c46309SBarry Smith }
2104b7c46309SBarry Smith 
21054a2ae208SSatish Balay #undef __FUNCT__
21064a2ae208SSatish Balay #define __FUNCT__ "MatDiagonalScale_MPIAIJ"
2107dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_MPIAIJ(Mat mat,Vec ll,Vec rr)
2108a008b906SSatish Balay {
21094b967eb1SSatish Balay   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)mat->data;
21104b967eb1SSatish Balay   Mat            a = aij->A,b = aij->B;
2111dfbe8321SBarry Smith   PetscErrorCode ierr;
2112b1d57f15SBarry Smith   PetscInt       s1,s2,s3;
2113a008b906SSatish Balay 
21143a40ed3dSBarry Smith   PetscFunctionBegin;
21154b967eb1SSatish Balay   ierr = MatGetLocalSize(mat,&s2,&s3);CHKERRQ(ierr);
21164b967eb1SSatish Balay   if (rr) {
2117e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&s1);CHKERRQ(ierr);
2118e32f2f54SBarry Smith     if (s1!=s3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"right vector non-conforming local size");
21194b967eb1SSatish Balay     /* Overlap communication with computation. */
2120ca9f406cSSatish Balay     ierr = VecScatterBegin(aij->Mvctx,rr,aij->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2121a008b906SSatish Balay   }
21224b967eb1SSatish Balay   if (ll) {
2123e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&s1);CHKERRQ(ierr);
2124e32f2f54SBarry Smith     if (s1!=s2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"left vector non-conforming local size");
2125f830108cSBarry Smith     ierr = (*b->ops->diagonalscale)(b,ll,0);CHKERRQ(ierr);
21264b967eb1SSatish Balay   }
21274b967eb1SSatish Balay   /* scale  the diagonal block */
2128f830108cSBarry Smith   ierr = (*a->ops->diagonalscale)(a,ll,rr);CHKERRQ(ierr);
21294b967eb1SSatish Balay 
21304b967eb1SSatish Balay   if (rr) {
21314b967eb1SSatish Balay     /* Do a scatter end and then right scale the off-diagonal block */
2132ca9f406cSSatish Balay     ierr = VecScatterEnd(aij->Mvctx,rr,aij->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2133f830108cSBarry Smith     ierr = (*b->ops->diagonalscale)(b,0,aij->lvec);CHKERRQ(ierr);
21344b967eb1SSatish Balay   }
21354b967eb1SSatish Balay 
21363a40ed3dSBarry Smith   PetscFunctionReturn(0);
2137a008b906SSatish Balay }
2138a008b906SSatish Balay 
21394a2ae208SSatish Balay #undef __FUNCT__
21404a2ae208SSatish Balay #define __FUNCT__ "MatSetUnfactored_MPIAIJ"
2141dfbe8321SBarry Smith PetscErrorCode MatSetUnfactored_MPIAIJ(Mat A)
2142bb5a7306SBarry Smith {
2143bb5a7306SBarry Smith   Mat_MPIAIJ     *a   = (Mat_MPIAIJ*)A->data;
2144dfbe8321SBarry Smith   PetscErrorCode ierr;
21453a40ed3dSBarry Smith 
21463a40ed3dSBarry Smith   PetscFunctionBegin;
2147bb5a7306SBarry Smith   ierr = MatSetUnfactored(a->A);CHKERRQ(ierr);
21483a40ed3dSBarry Smith   PetscFunctionReturn(0);
2149bb5a7306SBarry Smith }
2150bb5a7306SBarry Smith 
21514a2ae208SSatish Balay #undef __FUNCT__
21524a2ae208SSatish Balay #define __FUNCT__ "MatEqual_MPIAIJ"
2153ace3abfcSBarry Smith PetscErrorCode MatEqual_MPIAIJ(Mat A,Mat B,PetscBool  *flag)
2154d4bb536fSBarry Smith {
2155d4bb536fSBarry Smith   Mat_MPIAIJ     *matB = (Mat_MPIAIJ*)B->data,*matA = (Mat_MPIAIJ*)A->data;
2156d4bb536fSBarry Smith   Mat            a,b,c,d;
2157ace3abfcSBarry Smith   PetscBool      flg;
2158dfbe8321SBarry Smith   PetscErrorCode ierr;
2159d4bb536fSBarry Smith 
21603a40ed3dSBarry Smith   PetscFunctionBegin;
2161d4bb536fSBarry Smith   a = matA->A; b = matA->B;
2162d4bb536fSBarry Smith   c = matB->A; d = matB->B;
2163d4bb536fSBarry Smith 
2164d4bb536fSBarry Smith   ierr = MatEqual(a,c,&flg);CHKERRQ(ierr);
2165abc0a331SBarry Smith   if (flg) {
2166d4bb536fSBarry Smith     ierr = MatEqual(b,d,&flg);CHKERRQ(ierr);
2167d4bb536fSBarry Smith   }
21687adad957SLisandro Dalcin   ierr = MPI_Allreduce(&flg,flag,1,MPI_INT,MPI_LAND,((PetscObject)A)->comm);CHKERRQ(ierr);
21693a40ed3dSBarry Smith   PetscFunctionReturn(0);
2170d4bb536fSBarry Smith }
2171d4bb536fSBarry Smith 
21724a2ae208SSatish Balay #undef __FUNCT__
21734a2ae208SSatish Balay #define __FUNCT__ "MatCopy_MPIAIJ"
2174dfbe8321SBarry Smith PetscErrorCode MatCopy_MPIAIJ(Mat A,Mat B,MatStructure str)
2175cb5b572fSBarry Smith {
2176dfbe8321SBarry Smith   PetscErrorCode ierr;
2177cb5b572fSBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ *)A->data;
2178cb5b572fSBarry Smith   Mat_MPIAIJ     *b = (Mat_MPIAIJ *)B->data;
2179cb5b572fSBarry Smith 
2180cb5b572fSBarry Smith   PetscFunctionBegin;
218133f4a19fSKris Buschelman   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
218233f4a19fSKris Buschelman   if ((str != SAME_NONZERO_PATTERN) || (A->ops->copy != B->ops->copy)) {
2183cb5b572fSBarry Smith     /* because of the column compression in the off-processor part of the matrix a->B,
2184cb5b572fSBarry Smith        the number of columns in a->B and b->B may be different, hence we cannot call
2185cb5b572fSBarry Smith        the MatCopy() directly on the two parts. If need be, we can provide a more
2186cb5b572fSBarry Smith        efficient copy than the MatCopy_Basic() by first uncompressing the a->B matrices
2187cb5b572fSBarry Smith        then copying the submatrices */
2188cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
2189cb5b572fSBarry Smith   } else {
2190cb5b572fSBarry Smith     ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
2191cb5b572fSBarry Smith     ierr = MatCopy(a->B,b->B,str);CHKERRQ(ierr);
2192cb5b572fSBarry Smith   }
2193cb5b572fSBarry Smith   PetscFunctionReturn(0);
2194cb5b572fSBarry Smith }
2195cb5b572fSBarry Smith 
21964a2ae208SSatish Balay #undef __FUNCT__
21974994cf47SJed Brown #define __FUNCT__ "MatSetUp_MPIAIJ"
21984994cf47SJed Brown PetscErrorCode MatSetUp_MPIAIJ(Mat A)
2199273d9f13SBarry Smith {
2200dfbe8321SBarry Smith   PetscErrorCode ierr;
2201273d9f13SBarry Smith 
2202273d9f13SBarry Smith   PetscFunctionBegin;
2203273d9f13SBarry Smith   ierr =  MatMPIAIJSetPreallocation(A,PETSC_DEFAULT,0,PETSC_DEFAULT,0);CHKERRQ(ierr);
2204273d9f13SBarry Smith   PetscFunctionReturn(0);
2205273d9f13SBarry Smith }
2206273d9f13SBarry Smith 
2207ac90fabeSBarry Smith #undef __FUNCT__
220895b7e79eSJed Brown #define __FUNCT__ "MatAXPYGetPreallocation_MPIAIJ"
220995b7e79eSJed Brown /* This is the same as MatAXPYGetPreallocation_SeqAIJ, except that the local-to-global map is provided */
221095b7e79eSJed Brown static PetscErrorCode MatAXPYGetPreallocation_MPIAIJ(Mat Y,const PetscInt *yltog,Mat X,const PetscInt *xltog,PetscInt* nnz)
221195b7e79eSJed Brown {
221295b7e79eSJed Brown   PetscInt          i,m=Y->rmap->N;
221395b7e79eSJed Brown   Mat_SeqAIJ        *x = (Mat_SeqAIJ*)X->data;
221495b7e79eSJed Brown   Mat_SeqAIJ        *y = (Mat_SeqAIJ*)Y->data;
221595b7e79eSJed Brown   const PetscInt    *xi = x->i,*yi = y->i;
221695b7e79eSJed Brown 
221795b7e79eSJed Brown   PetscFunctionBegin;
221895b7e79eSJed Brown   /* Set the number of nonzeros in the new matrix */
221995b7e79eSJed Brown   for(i=0; i<m; i++) {
222095b7e79eSJed Brown     PetscInt j,k,nzx = xi[i+1] - xi[i],nzy = yi[i+1] - yi[i];
222195b7e79eSJed Brown     const PetscInt *xj = x->j+xi[i],*yj = y->j+yi[i];
222295b7e79eSJed Brown     nnz[i] = 0;
222395b7e79eSJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
222495b7e79eSJed Brown       for (; k<nzy && yltog[yj[k]]<xltog[xj[j]]; k++) nnz[i]++; /* Catch up to X */
222595b7e79eSJed Brown       if (k<nzy && yltog[yj[k]]==xltog[xj[j]]) k++;             /* Skip duplicate */
222695b7e79eSJed Brown       nnz[i]++;
222795b7e79eSJed Brown     }
222895b7e79eSJed Brown     for (; k<nzy; k++) nnz[i]++;
222995b7e79eSJed Brown   }
223095b7e79eSJed Brown   PetscFunctionReturn(0);
223195b7e79eSJed Brown }
223295b7e79eSJed Brown 
223395b7e79eSJed Brown #undef __FUNCT__
2234ac90fabeSBarry Smith #define __FUNCT__ "MatAXPY_MPIAIJ"
2235f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_MPIAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
2236ac90fabeSBarry Smith {
2237dfbe8321SBarry Smith   PetscErrorCode ierr;
2238b1d57f15SBarry Smith   PetscInt       i;
2239ac90fabeSBarry Smith   Mat_MPIAIJ     *xx = (Mat_MPIAIJ *)X->data,*yy = (Mat_MPIAIJ *)Y->data;
22404ce68768SBarry Smith   PetscBLASInt   bnz,one=1;
2241ac90fabeSBarry Smith   Mat_SeqAIJ     *x,*y;
2242ac90fabeSBarry Smith 
2243ac90fabeSBarry Smith   PetscFunctionBegin;
2244ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
2245f4df32b1SMatthew Knepley     PetscScalar alpha = a;
2246ac90fabeSBarry Smith     x = (Mat_SeqAIJ *)xx->A->data;
2247ac90fabeSBarry Smith     y = (Mat_SeqAIJ *)yy->A->data;
22480805154bSBarry Smith     bnz = PetscBLASIntCast(x->nz);
2249f4df32b1SMatthew Knepley     BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
2250ac90fabeSBarry Smith     x = (Mat_SeqAIJ *)xx->B->data;
2251ac90fabeSBarry Smith     y = (Mat_SeqAIJ *)yy->B->data;
22520805154bSBarry Smith     bnz = PetscBLASIntCast(x->nz);
2253f4df32b1SMatthew Knepley     BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
2254a30b2313SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) {
2255f4df32b1SMatthew Knepley     ierr = MatAXPY_SeqAIJ(yy->A,a,xx->A,str);CHKERRQ(ierr);
2256c537a176SHong Zhang 
2257c537a176SHong Zhang     x = (Mat_SeqAIJ *)xx->B->data;
2258a30b2313SHong Zhang     y = (Mat_SeqAIJ *)yy->B->data;
2259a30b2313SHong Zhang     if (y->xtoy && y->XtoY != xx->B) {
2260a30b2313SHong Zhang       ierr = PetscFree(y->xtoy);CHKERRQ(ierr);
22616bf464f9SBarry Smith       ierr = MatDestroy(&y->XtoY);CHKERRQ(ierr);
2262c537a176SHong Zhang     }
2263a30b2313SHong Zhang     if (!y->xtoy) { /* get xtoy */
2264d0f46423SBarry Smith       ierr = MatAXPYGetxtoy_Private(xx->B->rmap->n,x->i,x->j,xx->garray,y->i,y->j,yy->garray,&y->xtoy);CHKERRQ(ierr);
2265a30b2313SHong Zhang       y->XtoY = xx->B;
2266407f6b05SHong Zhang       ierr = PetscObjectReference((PetscObject)xx->B);CHKERRQ(ierr);
2267c537a176SHong Zhang     }
2268f4df32b1SMatthew Knepley     for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += a*(x->a[i]);
2269ac90fabeSBarry Smith   } else {
22709f5f6813SShri Abhyankar     Mat B;
22719f5f6813SShri Abhyankar     PetscInt *nnz_d,*nnz_o;
22729f5f6813SShri Abhyankar     ierr = PetscMalloc(yy->A->rmap->N*sizeof(PetscInt),&nnz_d);CHKERRQ(ierr);
22739f5f6813SShri Abhyankar     ierr = PetscMalloc(yy->B->rmap->N*sizeof(PetscInt),&nnz_o);CHKERRQ(ierr);
22749f5f6813SShri Abhyankar     ierr = MatCreate(((PetscObject)Y)->comm,&B);CHKERRQ(ierr);
2275bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
22769f5f6813SShri Abhyankar     ierr = MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);CHKERRQ(ierr);
2277a2f3521dSMark F. Adams     ierr = MatSetBlockSizes(B,Y->rmap->bs,Y->cmap->bs);CHKERRQ(ierr);
22789f5f6813SShri Abhyankar     ierr = MatSetType(B,MATMPIAIJ);CHKERRQ(ierr);
22799f5f6813SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(yy->A,xx->A,nnz_d);CHKERRQ(ierr);
228095b7e79eSJed Brown     ierr = MatAXPYGetPreallocation_MPIAIJ(yy->B,yy->garray,xx->B,xx->garray,nnz_o);CHKERRQ(ierr);
2281ecd8bba6SJed Brown     ierr = MatMPIAIJSetPreallocation(B,0,nnz_d,0,nnz_o);CHKERRQ(ierr);
22829f5f6813SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
22839f5f6813SShri Abhyankar     ierr = MatHeaderReplace(Y,B);
22849f5f6813SShri Abhyankar     ierr = PetscFree(nnz_d);CHKERRQ(ierr);
22859f5f6813SShri Abhyankar     ierr = PetscFree(nnz_o);CHKERRQ(ierr);
2286ac90fabeSBarry Smith   }
2287ac90fabeSBarry Smith   PetscFunctionReturn(0);
2288ac90fabeSBarry Smith }
2289ac90fabeSBarry Smith 
22907087cfbeSBarry Smith extern PetscErrorCode  MatConjugate_SeqAIJ(Mat);
2291354c94deSBarry Smith 
2292354c94deSBarry Smith #undef __FUNCT__
2293354c94deSBarry Smith #define __FUNCT__ "MatConjugate_MPIAIJ"
22947087cfbeSBarry Smith PetscErrorCode  MatConjugate_MPIAIJ(Mat mat)
2295354c94deSBarry Smith {
2296354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
2297354c94deSBarry Smith   PetscErrorCode ierr;
2298354c94deSBarry Smith   Mat_MPIAIJ     *aij = (Mat_MPIAIJ *)mat->data;
2299354c94deSBarry Smith 
2300354c94deSBarry Smith   PetscFunctionBegin;
2301354c94deSBarry Smith   ierr = MatConjugate_SeqAIJ(aij->A);CHKERRQ(ierr);
2302354c94deSBarry Smith   ierr = MatConjugate_SeqAIJ(aij->B);CHKERRQ(ierr);
2303354c94deSBarry Smith #else
2304354c94deSBarry Smith   PetscFunctionBegin;
2305354c94deSBarry Smith #endif
2306354c94deSBarry Smith   PetscFunctionReturn(0);
2307354c94deSBarry Smith }
2308354c94deSBarry Smith 
230999cafbc1SBarry Smith #undef __FUNCT__
231099cafbc1SBarry Smith #define __FUNCT__ "MatRealPart_MPIAIJ"
231199cafbc1SBarry Smith PetscErrorCode MatRealPart_MPIAIJ(Mat A)
231299cafbc1SBarry Smith {
231399cafbc1SBarry Smith   Mat_MPIAIJ   *a = (Mat_MPIAIJ*)A->data;
231499cafbc1SBarry Smith   PetscErrorCode ierr;
231599cafbc1SBarry Smith 
231699cafbc1SBarry Smith   PetscFunctionBegin;
231799cafbc1SBarry Smith   ierr = MatRealPart(a->A);CHKERRQ(ierr);
231899cafbc1SBarry Smith   ierr = MatRealPart(a->B);CHKERRQ(ierr);
231999cafbc1SBarry Smith   PetscFunctionReturn(0);
232099cafbc1SBarry Smith }
232199cafbc1SBarry Smith 
232299cafbc1SBarry Smith #undef __FUNCT__
232399cafbc1SBarry Smith #define __FUNCT__ "MatImaginaryPart_MPIAIJ"
232499cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_MPIAIJ(Mat A)
232599cafbc1SBarry Smith {
232699cafbc1SBarry Smith   Mat_MPIAIJ   *a = (Mat_MPIAIJ*)A->data;
232799cafbc1SBarry Smith   PetscErrorCode ierr;
232899cafbc1SBarry Smith 
232999cafbc1SBarry Smith   PetscFunctionBegin;
233099cafbc1SBarry Smith   ierr = MatImaginaryPart(a->A);CHKERRQ(ierr);
233199cafbc1SBarry Smith   ierr = MatImaginaryPart(a->B);CHKERRQ(ierr);
233299cafbc1SBarry Smith   PetscFunctionReturn(0);
233399cafbc1SBarry Smith }
233499cafbc1SBarry Smith 
2335103bf8bdSMatthew Knepley #ifdef PETSC_HAVE_PBGL
2336103bf8bdSMatthew Knepley 
2337103bf8bdSMatthew Knepley #include <boost/parallel/mpi/bsp_process_group.hpp>
2338a2c909beSMatthew Knepley #include <boost/graph/distributed/ilu_default_graph.hpp>
2339a2c909beSMatthew Knepley #include <boost/graph/distributed/ilu_0_block.hpp>
2340a2c909beSMatthew Knepley #include <boost/graph/distributed/ilu_preconditioner.hpp>
2341103bf8bdSMatthew Knepley #include <boost/graph/distributed/petsc/interface.hpp>
2342a2c909beSMatthew Knepley #include <boost/multi_array.hpp>
2343d0f46423SBarry Smith #include <boost/parallel/distributed_property_map->hpp>
2344103bf8bdSMatthew Knepley 
2345103bf8bdSMatthew Knepley #undef __FUNCT__
2346103bf8bdSMatthew Knepley #define __FUNCT__ "MatILUFactorSymbolic_MPIAIJ"
2347103bf8bdSMatthew Knepley /*
2348103bf8bdSMatthew Knepley   This uses the parallel ILU factorization of Peter Gottschling <pgottsch@osl.iu.edu>
2349103bf8bdSMatthew Knepley */
23500481f469SBarry Smith PetscErrorCode MatILUFactorSymbolic_MPIAIJ(Mat fact,Mat A, IS isrow, IS iscol, const MatFactorInfo *info)
2351103bf8bdSMatthew Knepley {
2352a2c909beSMatthew Knepley   namespace petsc = boost::distributed::petsc;
2353a2c909beSMatthew Knepley 
2354a2c909beSMatthew Knepley   namespace graph_dist = boost::graph::distributed;
2355a2c909beSMatthew Knepley   using boost::graph::distributed::ilu_default::process_group_type;
2356a2c909beSMatthew Knepley   using boost::graph::ilu_permuted;
2357a2c909beSMatthew Knepley 
2358ace3abfcSBarry Smith   PetscBool       row_identity, col_identity;
2359776b82aeSLisandro Dalcin   PetscContainer  c;
2360103bf8bdSMatthew Knepley   PetscInt        m, n, M, N;
2361103bf8bdSMatthew Knepley   PetscErrorCode  ierr;
2362103bf8bdSMatthew Knepley 
2363103bf8bdSMatthew Knepley   PetscFunctionBegin;
2364e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels = 0 supported for parallel ilu");
2365103bf8bdSMatthew Knepley   ierr = ISIdentity(isrow, &row_identity);CHKERRQ(ierr);
2366103bf8bdSMatthew Knepley   ierr = ISIdentity(iscol, &col_identity);CHKERRQ(ierr);
2367103bf8bdSMatthew Knepley   if (!row_identity || !col_identity) {
2368e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Row and column permutations must be identity for parallel ILU");
2369103bf8bdSMatthew Knepley   }
2370103bf8bdSMatthew Knepley 
2371103bf8bdSMatthew Knepley   process_group_type pg;
2372a2c909beSMatthew Knepley   typedef graph_dist::ilu_default::ilu_level_graph_type  lgraph_type;
2373a2c909beSMatthew Knepley   lgraph_type*   lgraph_p = new lgraph_type(petsc::num_global_vertices(A), pg, petsc::matrix_distribution(A, pg));
2374a2c909beSMatthew Knepley   lgraph_type&   level_graph = *lgraph_p;
2375a2c909beSMatthew Knepley   graph_dist::ilu_default::graph_type&            graph(level_graph.graph);
2376a2c909beSMatthew Knepley 
2377103bf8bdSMatthew Knepley   petsc::read_matrix(A, graph, get(boost::edge_weight, graph));
2378a2c909beSMatthew Knepley   ilu_permuted(level_graph);
2379103bf8bdSMatthew Knepley 
2380103bf8bdSMatthew Knepley   /* put together the new matrix */
23817adad957SLisandro Dalcin   ierr = MatCreate(((PetscObject)A)->comm, fact);CHKERRQ(ierr);
2382103bf8bdSMatthew Knepley   ierr = MatGetLocalSize(A, &m, &n);CHKERRQ(ierr);
2383103bf8bdSMatthew Knepley   ierr = MatGetSize(A, &M, &N);CHKERRQ(ierr);
2384719d5645SBarry Smith   ierr = MatSetSizes(fact, m, n, M, N);CHKERRQ(ierr);
2385a2f3521dSMark F. Adams   ierr = MatSetBlockSizes(fact,A->rmap->bs,A->cmap->bs); CHKERRQ(ierr);
2386719d5645SBarry Smith   ierr = MatSetType(fact, ((PetscObject)A)->type_name);CHKERRQ(ierr);
2387719d5645SBarry Smith   ierr = MatAssemblyBegin(fact, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2388719d5645SBarry Smith   ierr = MatAssemblyEnd(fact, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2389103bf8bdSMatthew Knepley 
23907adad957SLisandro Dalcin   ierr = PetscContainerCreate(((PetscObject)A)->comm, &c);
2391776b82aeSLisandro Dalcin   ierr = PetscContainerSetPointer(c, lgraph_p);
2392719d5645SBarry Smith   ierr = PetscObjectCompose((PetscObject) (fact), "graph", (PetscObject) c);
2393bf0cc555SLisandro Dalcin   ierr = PetscContainerDestroy(&c);
2394103bf8bdSMatthew Knepley   PetscFunctionReturn(0);
2395103bf8bdSMatthew Knepley }
2396103bf8bdSMatthew Knepley 
2397103bf8bdSMatthew Knepley #undef __FUNCT__
2398103bf8bdSMatthew Knepley #define __FUNCT__ "MatLUFactorNumeric_MPIAIJ"
23990481f469SBarry Smith PetscErrorCode MatLUFactorNumeric_MPIAIJ(Mat B,Mat A, const MatFactorInfo *info)
2400103bf8bdSMatthew Knepley {
2401103bf8bdSMatthew Knepley   PetscFunctionBegin;
2402103bf8bdSMatthew Knepley   PetscFunctionReturn(0);
2403103bf8bdSMatthew Knepley }
2404103bf8bdSMatthew Knepley 
2405103bf8bdSMatthew Knepley #undef __FUNCT__
2406103bf8bdSMatthew Knepley #define __FUNCT__ "MatSolve_MPIAIJ"
2407103bf8bdSMatthew Knepley /*
2408103bf8bdSMatthew Knepley   This uses the parallel ILU factorization of Peter Gottschling <pgottsch@osl.iu.edu>
2409103bf8bdSMatthew Knepley */
2410103bf8bdSMatthew Knepley PetscErrorCode MatSolve_MPIAIJ(Mat A, Vec b, Vec x)
2411103bf8bdSMatthew Knepley {
2412a2c909beSMatthew Knepley   namespace graph_dist = boost::graph::distributed;
2413a2c909beSMatthew Knepley 
2414a2c909beSMatthew Knepley   typedef graph_dist::ilu_default::ilu_level_graph_type  lgraph_type;
2415a2c909beSMatthew Knepley   lgraph_type*   lgraph_p;
2416776b82aeSLisandro Dalcin   PetscContainer c;
2417103bf8bdSMatthew Knepley   PetscErrorCode ierr;
2418103bf8bdSMatthew Knepley 
2419103bf8bdSMatthew Knepley   PetscFunctionBegin;
2420103bf8bdSMatthew Knepley   ierr = PetscObjectQuery((PetscObject) A, "graph", (PetscObject *) &c);CHKERRQ(ierr);
2421776b82aeSLisandro Dalcin   ierr = PetscContainerGetPointer(c, (void **) &lgraph_p);CHKERRQ(ierr);
2422103bf8bdSMatthew Knepley   ierr = VecCopy(b, x);CHKERRQ(ierr);
2423a2c909beSMatthew Knepley 
2424a2c909beSMatthew Knepley   PetscScalar* array_x;
2425a2c909beSMatthew Knepley   ierr = VecGetArray(x, &array_x);CHKERRQ(ierr);
2426a2c909beSMatthew Knepley   PetscInt sx;
2427a2c909beSMatthew Knepley   ierr = VecGetSize(x, &sx);CHKERRQ(ierr);
2428a2c909beSMatthew Knepley 
2429a2c909beSMatthew Knepley   PetscScalar* array_b;
2430a2c909beSMatthew Knepley   ierr = VecGetArray(b, &array_b);CHKERRQ(ierr);
2431a2c909beSMatthew Knepley   PetscInt sb;
2432a2c909beSMatthew Knepley   ierr = VecGetSize(b, &sb);CHKERRQ(ierr);
2433a2c909beSMatthew Knepley 
2434a2c909beSMatthew Knepley   lgraph_type&   level_graph = *lgraph_p;
2435a2c909beSMatthew Knepley   graph_dist::ilu_default::graph_type&            graph(level_graph.graph);
2436a2c909beSMatthew Knepley 
2437a2c909beSMatthew Knepley   typedef boost::multi_array_ref<PetscScalar, 1> array_ref_type;
2438a2c909beSMatthew Knepley   array_ref_type                                 ref_b(array_b, boost::extents[num_vertices(graph)]),
2439a2c909beSMatthew Knepley                                                  ref_x(array_x, boost::extents[num_vertices(graph)]);
2440a2c909beSMatthew Knepley 
2441a2c909beSMatthew Knepley   typedef boost::iterator_property_map<array_ref_type::iterator,
2442a2c909beSMatthew Knepley                                 boost::property_map<graph_dist::ilu_default::graph_type, boost::vertex_index_t>::type>  gvector_type;
2443a2c909beSMatthew Knepley   gvector_type                                   vector_b(ref_b.begin(), get(boost::vertex_index, graph)),
2444a2c909beSMatthew Knepley                                                  vector_x(ref_x.begin(), get(boost::vertex_index, graph));
2445a2c909beSMatthew Knepley 
2446a2c909beSMatthew Knepley   ilu_set_solve(*lgraph_p, vector_b, vector_x);
2447a2c909beSMatthew Knepley 
2448103bf8bdSMatthew Knepley   PetscFunctionReturn(0);
2449103bf8bdSMatthew Knepley }
2450103bf8bdSMatthew Knepley #endif
2451103bf8bdSMatthew Knepley 
245269db28dcSHong Zhang typedef struct { /* used by MatGetRedundantMatrix() for reusing matredundant */
245369db28dcSHong Zhang   PetscInt       nzlocal,nsends,nrecvs;
24541d79065fSBarry Smith   PetscMPIInt    *send_rank,*recv_rank;
24551d79065fSBarry Smith   PetscInt       *sbuf_nz,*rbuf_nz,*sbuf_j,**rbuf_j;
245669db28dcSHong Zhang   PetscScalar    *sbuf_a,**rbuf_a;
2457bf0cc555SLisandro Dalcin   PetscErrorCode (*Destroy)(Mat);
245869db28dcSHong Zhang } Mat_Redundant;
245969db28dcSHong Zhang 
246069db28dcSHong Zhang #undef __FUNCT__
246169db28dcSHong Zhang #define __FUNCT__ "PetscContainerDestroy_MatRedundant"
246269db28dcSHong Zhang PetscErrorCode PetscContainerDestroy_MatRedundant(void *ptr)
246369db28dcSHong Zhang {
246469db28dcSHong Zhang   PetscErrorCode       ierr;
246569db28dcSHong Zhang   Mat_Redundant        *redund=(Mat_Redundant*)ptr;
246669db28dcSHong Zhang   PetscInt             i;
246769db28dcSHong Zhang 
246869db28dcSHong Zhang   PetscFunctionBegin;
24691d79065fSBarry Smith   ierr = PetscFree2(redund->send_rank,redund->recv_rank);CHKERRQ(ierr);
247069db28dcSHong Zhang   ierr = PetscFree(redund->sbuf_j);CHKERRQ(ierr);
247169db28dcSHong Zhang   ierr = PetscFree(redund->sbuf_a);CHKERRQ(ierr);
247269db28dcSHong Zhang   for (i=0; i<redund->nrecvs; i++){
247369db28dcSHong Zhang     ierr = PetscFree(redund->rbuf_j[i]);CHKERRQ(ierr);
247469db28dcSHong Zhang     ierr = PetscFree(redund->rbuf_a[i]);CHKERRQ(ierr);
247569db28dcSHong Zhang   }
24761d79065fSBarry Smith   ierr = PetscFree4(redund->sbuf_nz,redund->rbuf_nz,redund->rbuf_j,redund->rbuf_a);CHKERRQ(ierr);
247769db28dcSHong Zhang   ierr = PetscFree(redund);CHKERRQ(ierr);
247869db28dcSHong Zhang   PetscFunctionReturn(0);
247969db28dcSHong Zhang }
248069db28dcSHong Zhang 
248169db28dcSHong Zhang #undef __FUNCT__
248269db28dcSHong Zhang #define __FUNCT__ "MatDestroy_MatRedundant"
248369db28dcSHong Zhang PetscErrorCode MatDestroy_MatRedundant(Mat A)
248469db28dcSHong Zhang {
248569db28dcSHong Zhang   PetscErrorCode  ierr;
248669db28dcSHong Zhang   PetscContainer  container;
248769db28dcSHong Zhang   Mat_Redundant   *redund=PETSC_NULL;
248869db28dcSHong Zhang 
248969db28dcSHong Zhang   PetscFunctionBegin;
249069db28dcSHong Zhang   ierr = PetscObjectQuery((PetscObject)A,"Mat_Redundant",(PetscObject *)&container);CHKERRQ(ierr);
2491bf0cc555SLisandro Dalcin   if (!container) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Container does not exit");
249269db28dcSHong Zhang   ierr = PetscContainerGetPointer(container,(void **)&redund);CHKERRQ(ierr);
2493bf0cc555SLisandro Dalcin   A->ops->destroy = redund->Destroy;
249469db28dcSHong Zhang   ierr = PetscObjectCompose((PetscObject)A,"Mat_Redundant",0);CHKERRQ(ierr);
2495bf0cc555SLisandro Dalcin   if (A->ops->destroy) {
249669db28dcSHong Zhang     ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
2497bf0cc555SLisandro Dalcin   }
249869db28dcSHong Zhang   PetscFunctionReturn(0);
249969db28dcSHong Zhang }
250069db28dcSHong Zhang 
250169db28dcSHong Zhang #undef __FUNCT__
250269db28dcSHong Zhang #define __FUNCT__ "MatGetRedundantMatrix_MPIAIJ"
250369db28dcSHong Zhang PetscErrorCode MatGetRedundantMatrix_MPIAIJ(Mat mat,PetscInt nsubcomm,MPI_Comm subcomm,PetscInt mlocal_sub,MatReuse reuse,Mat *matredundant)
250469db28dcSHong Zhang {
250569db28dcSHong Zhang   PetscMPIInt    rank,size;
25067adad957SLisandro Dalcin   MPI_Comm       comm=((PetscObject)mat)->comm;
250769db28dcSHong Zhang   PetscErrorCode ierr;
250869db28dcSHong Zhang   PetscInt       nsends=0,nrecvs=0,i,rownz_max=0;
250969db28dcSHong Zhang   PetscMPIInt    *send_rank=PETSC_NULL,*recv_rank=PETSC_NULL;
2510d0f46423SBarry Smith   PetscInt       *rowrange=mat->rmap->range;
251169db28dcSHong Zhang   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)mat->data;
251269db28dcSHong Zhang   Mat            A=aij->A,B=aij->B,C=*matredundant;
251369db28dcSHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b=(Mat_SeqAIJ*)B->data;
251469db28dcSHong Zhang   PetscScalar    *sbuf_a;
251569db28dcSHong Zhang   PetscInt       nzlocal=a->nz+b->nz;
2516d0f46423SBarry Smith   PetscInt       j,cstart=mat->cmap->rstart,cend=mat->cmap->rend,row,nzA,nzB,ncols,*cworkA,*cworkB;
2517d0f46423SBarry Smith   PetscInt       rstart=mat->rmap->rstart,rend=mat->rmap->rend,*bmap=aij->garray,M,N;
251869db28dcSHong Zhang   PetscInt       *cols,ctmp,lwrite,*rptr,l,*sbuf_j;
2519a77337e4SBarry Smith   MatScalar      *aworkA,*aworkB;
2520a77337e4SBarry Smith   PetscScalar    *vals;
252169db28dcSHong Zhang   PetscMPIInt    tag1,tag2,tag3,imdex;
252269db28dcSHong Zhang   MPI_Request    *s_waits1=PETSC_NULL,*s_waits2=PETSC_NULL,*s_waits3=PETSC_NULL,
252369db28dcSHong Zhang                  *r_waits1=PETSC_NULL,*r_waits2=PETSC_NULL,*r_waits3=PETSC_NULL;
252469db28dcSHong Zhang   MPI_Status     recv_status,*send_status;
252569db28dcSHong Zhang   PetscInt       *sbuf_nz=PETSC_NULL,*rbuf_nz=PETSC_NULL,count;
252669db28dcSHong Zhang   PetscInt       **rbuf_j=PETSC_NULL;
252769db28dcSHong Zhang   PetscScalar    **rbuf_a=PETSC_NULL;
252869db28dcSHong Zhang   Mat_Redundant  *redund=PETSC_NULL;
252969db28dcSHong Zhang   PetscContainer container;
253069db28dcSHong Zhang 
253169db28dcSHong Zhang   PetscFunctionBegin;
253269db28dcSHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
253369db28dcSHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
253469db28dcSHong Zhang 
253569db28dcSHong Zhang   if (reuse == MAT_REUSE_MATRIX) {
253669db28dcSHong Zhang     ierr = MatGetSize(C,&M,&N);CHKERRQ(ierr);
2537e32f2f54SBarry Smith     if (M != N || M != mat->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. Wrong global size");
253869db28dcSHong Zhang     ierr = MatGetLocalSize(C,&M,&N);CHKERRQ(ierr);
2539e32f2f54SBarry Smith     if (M != N || M != mlocal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. Wrong local size");
254069db28dcSHong Zhang     ierr = PetscObjectQuery((PetscObject)C,"Mat_Redundant",(PetscObject *)&container);CHKERRQ(ierr);
2541bf0cc555SLisandro Dalcin     if (!container) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Container does not exit");
254269db28dcSHong Zhang     ierr = PetscContainerGetPointer(container,(void **)&redund);CHKERRQ(ierr);
2543e32f2f54SBarry Smith     if (nzlocal != redund->nzlocal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. Wrong nzlocal");
254469db28dcSHong Zhang 
254569db28dcSHong Zhang     nsends    = redund->nsends;
254669db28dcSHong Zhang     nrecvs    = redund->nrecvs;
25471d79065fSBarry Smith     send_rank = redund->send_rank;
25481d79065fSBarry Smith     recv_rank = redund->recv_rank;
25491d79065fSBarry Smith     sbuf_nz   = redund->sbuf_nz;
25501d79065fSBarry Smith     rbuf_nz   = redund->rbuf_nz;
255169db28dcSHong Zhang     sbuf_j    = redund->sbuf_j;
255269db28dcSHong Zhang     sbuf_a    = redund->sbuf_a;
255369db28dcSHong Zhang     rbuf_j    = redund->rbuf_j;
255469db28dcSHong Zhang     rbuf_a    = redund->rbuf_a;
255569db28dcSHong Zhang   }
255669db28dcSHong Zhang 
255769db28dcSHong Zhang   if (reuse == MAT_INITIAL_MATRIX){
255869db28dcSHong Zhang     PetscMPIInt  subrank,subsize;
255969db28dcSHong Zhang     PetscInt     nleftover,np_subcomm;
256069db28dcSHong Zhang     /* get the destination processors' id send_rank, nsends and nrecvs */
256169db28dcSHong Zhang     ierr = MPI_Comm_rank(subcomm,&subrank);CHKERRQ(ierr);
256269db28dcSHong Zhang     ierr = MPI_Comm_size(subcomm,&subsize);CHKERRQ(ierr);
25631d79065fSBarry Smith     ierr = PetscMalloc2(size,PetscMPIInt,&send_rank,size,PetscMPIInt,&recv_rank);
256469db28dcSHong Zhang     np_subcomm = size/nsubcomm;
256569db28dcSHong Zhang     nleftover  = size - nsubcomm*np_subcomm;
256669db28dcSHong Zhang     nsends = 0; nrecvs = 0;
256769db28dcSHong Zhang     for (i=0; i<size; i++){ /* i=rank*/
256869db28dcSHong Zhang       if (subrank == i/nsubcomm && rank != i){ /* my_subrank == other's subrank */
256969db28dcSHong Zhang         send_rank[nsends] = i; nsends++;
257069db28dcSHong Zhang         recv_rank[nrecvs++] = i;
257169db28dcSHong Zhang       }
257269db28dcSHong Zhang     }
257369db28dcSHong Zhang     if (rank >= size - nleftover){/* this proc is a leftover processor */
257469db28dcSHong Zhang       i = size-nleftover-1;
257569db28dcSHong Zhang       j = 0;
257669db28dcSHong Zhang       while (j < nsubcomm - nleftover){
257769db28dcSHong Zhang         send_rank[nsends++] = i;
257869db28dcSHong Zhang         i--; j++;
257969db28dcSHong Zhang       }
258069db28dcSHong Zhang     }
258169db28dcSHong Zhang 
258269db28dcSHong Zhang     if (nleftover && subsize == size/nsubcomm && subrank==subsize-1){ /* this proc recvs from leftover processors */
258369db28dcSHong Zhang       for (i=0; i<nleftover; i++){
258469db28dcSHong Zhang         recv_rank[nrecvs++] = size-nleftover+i;
258569db28dcSHong Zhang       }
258669db28dcSHong Zhang     }
258769db28dcSHong Zhang 
258869db28dcSHong Zhang     /* allocate sbuf_j, sbuf_a */
258969db28dcSHong Zhang     i = nzlocal + rowrange[rank+1] - rowrange[rank] + 2;
259069db28dcSHong Zhang     ierr = PetscMalloc(i*sizeof(PetscInt),&sbuf_j);CHKERRQ(ierr);
259169db28dcSHong Zhang     ierr = PetscMalloc((nzlocal+1)*sizeof(PetscScalar),&sbuf_a);CHKERRQ(ierr);
259269db28dcSHong Zhang   } /* endof if (reuse == MAT_INITIAL_MATRIX) */
259369db28dcSHong Zhang 
259469db28dcSHong Zhang   /* copy mat's local entries into the buffers */
259569db28dcSHong Zhang   if (reuse == MAT_INITIAL_MATRIX){
259669db28dcSHong Zhang     rownz_max = 0;
259769db28dcSHong Zhang     rptr = sbuf_j;
259869db28dcSHong Zhang     cols = sbuf_j + rend-rstart + 1;
259969db28dcSHong Zhang     vals = sbuf_a;
260069db28dcSHong Zhang     rptr[0] = 0;
260169db28dcSHong Zhang     for (i=0; i<rend-rstart; i++){
260269db28dcSHong Zhang       row = i + rstart;
260369db28dcSHong Zhang       nzA    = a->i[i+1] - a->i[i]; nzB = b->i[i+1] - b->i[i];
260469db28dcSHong Zhang       ncols  = nzA + nzB;
260569db28dcSHong Zhang       cworkA = a->j + a->i[i]; cworkB = b->j + b->i[i];
260669db28dcSHong Zhang       aworkA = a->a + a->i[i]; aworkB = b->a + b->i[i];
260769db28dcSHong Zhang       /* load the column indices for this row into cols */
260869db28dcSHong Zhang       lwrite = 0;
260969db28dcSHong Zhang       for (l=0; l<nzB; l++) {
261069db28dcSHong Zhang         if ((ctmp = bmap[cworkB[l]]) < cstart){
261169db28dcSHong Zhang           vals[lwrite]   = aworkB[l];
261269db28dcSHong Zhang           cols[lwrite++] = ctmp;
261369db28dcSHong Zhang         }
261469db28dcSHong Zhang       }
261569db28dcSHong Zhang       for (l=0; l<nzA; l++){
261669db28dcSHong Zhang         vals[lwrite]   = aworkA[l];
261769db28dcSHong Zhang         cols[lwrite++] = cstart + cworkA[l];
261869db28dcSHong Zhang       }
261969db28dcSHong Zhang       for (l=0; l<nzB; l++) {
262069db28dcSHong Zhang         if ((ctmp = bmap[cworkB[l]]) >= cend){
262169db28dcSHong Zhang           vals[lwrite]   = aworkB[l];
262269db28dcSHong Zhang           cols[lwrite++] = ctmp;
262369db28dcSHong Zhang         }
262469db28dcSHong Zhang       }
262569db28dcSHong Zhang       vals += ncols;
262669db28dcSHong Zhang       cols += ncols;
262769db28dcSHong Zhang       rptr[i+1] = rptr[i] + ncols;
262869db28dcSHong Zhang       if (rownz_max < ncols) rownz_max = ncols;
262969db28dcSHong Zhang     }
2630e32f2f54SBarry Smith     if (rptr[rend-rstart] != a->nz + b->nz) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB, "rptr[%d] %d != %d + %d",rend-rstart,rptr[rend-rstart+1],a->nz,b->nz);
263169db28dcSHong Zhang   } else { /* only copy matrix values into sbuf_a */
263269db28dcSHong Zhang     rptr = sbuf_j;
263369db28dcSHong Zhang     vals = sbuf_a;
263469db28dcSHong Zhang     rptr[0] = 0;
263569db28dcSHong Zhang     for (i=0; i<rend-rstart; i++){
263669db28dcSHong Zhang       row = i + rstart;
263769db28dcSHong Zhang       nzA    = a->i[i+1] - a->i[i]; nzB = b->i[i+1] - b->i[i];
263869db28dcSHong Zhang       ncols  = nzA + nzB;
263969db28dcSHong Zhang       cworkA = a->j + a->i[i]; cworkB = b->j + b->i[i];
264069db28dcSHong Zhang       aworkA = a->a + a->i[i]; aworkB = b->a + b->i[i];
264169db28dcSHong Zhang       lwrite = 0;
264269db28dcSHong Zhang       for (l=0; l<nzB; l++) {
264369db28dcSHong Zhang         if ((ctmp = bmap[cworkB[l]]) < cstart) vals[lwrite++] = aworkB[l];
264469db28dcSHong Zhang       }
264569db28dcSHong Zhang       for (l=0; l<nzA; l++) vals[lwrite++] = aworkA[l];
264669db28dcSHong Zhang       for (l=0; l<nzB; l++) {
264769db28dcSHong Zhang         if ((ctmp = bmap[cworkB[l]]) >= cend) vals[lwrite++] = aworkB[l];
264869db28dcSHong Zhang       }
264969db28dcSHong Zhang       vals += ncols;
265069db28dcSHong Zhang       rptr[i+1] = rptr[i] + ncols;
265169db28dcSHong Zhang     }
265269db28dcSHong Zhang   } /* endof if (reuse == MAT_INITIAL_MATRIX) */
265369db28dcSHong Zhang 
265469db28dcSHong Zhang   /* send nzlocal to others, and recv other's nzlocal */
265569db28dcSHong Zhang   /*--------------------------------------------------*/
265669db28dcSHong Zhang   if (reuse == MAT_INITIAL_MATRIX){
265769db28dcSHong Zhang     ierr = PetscMalloc2(3*(nsends + nrecvs)+1,MPI_Request,&s_waits3,nsends+1,MPI_Status,&send_status);CHKERRQ(ierr);
265869db28dcSHong Zhang     s_waits2 = s_waits3 + nsends;
265969db28dcSHong Zhang     s_waits1 = s_waits2 + nsends;
266069db28dcSHong Zhang     r_waits1 = s_waits1 + nsends;
266169db28dcSHong Zhang     r_waits2 = r_waits1 + nrecvs;
266269db28dcSHong Zhang     r_waits3 = r_waits2 + nrecvs;
266369db28dcSHong Zhang   } else {
266469db28dcSHong Zhang     ierr = PetscMalloc2(nsends + nrecvs +1,MPI_Request,&s_waits3,nsends+1,MPI_Status,&send_status);CHKERRQ(ierr);
266569db28dcSHong Zhang     r_waits3 = s_waits3 + nsends;
266669db28dcSHong Zhang   }
266769db28dcSHong Zhang 
266869db28dcSHong Zhang   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag3);CHKERRQ(ierr);
266969db28dcSHong Zhang   if (reuse == MAT_INITIAL_MATRIX){
267069db28dcSHong Zhang     /* get new tags to keep the communication clean */
267169db28dcSHong Zhang     ierr = PetscObjectGetNewTag((PetscObject)mat,&tag1);CHKERRQ(ierr);
267269db28dcSHong Zhang     ierr = PetscObjectGetNewTag((PetscObject)mat,&tag2);CHKERRQ(ierr);
26731d79065fSBarry Smith     ierr = PetscMalloc4(nsends,PetscInt,&sbuf_nz,nrecvs,PetscInt,&rbuf_nz,nrecvs,PetscInt*,&rbuf_j,nrecvs,PetscScalar*,&rbuf_a);CHKERRQ(ierr);
267469db28dcSHong Zhang 
267569db28dcSHong Zhang     /* post receives of other's nzlocal */
267669db28dcSHong Zhang     for (i=0; i<nrecvs; i++){
267769db28dcSHong Zhang       ierr = MPI_Irecv(rbuf_nz+i,1,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,r_waits1+i);CHKERRQ(ierr);
267869db28dcSHong Zhang     }
267969db28dcSHong Zhang     /* send nzlocal to others */
268069db28dcSHong Zhang     for (i=0; i<nsends; i++){
268169db28dcSHong Zhang       sbuf_nz[i] = nzlocal;
268269db28dcSHong Zhang       ierr = MPI_Isend(sbuf_nz+i,1,MPIU_INT,send_rank[i],tag1,comm,s_waits1+i);CHKERRQ(ierr);
268369db28dcSHong Zhang     }
268469db28dcSHong Zhang     /* wait on receives of nzlocal; allocate space for rbuf_j, rbuf_a */
268569db28dcSHong Zhang     count = nrecvs;
268669db28dcSHong Zhang     while (count) {
268769db28dcSHong Zhang       ierr = MPI_Waitany(nrecvs,r_waits1,&imdex,&recv_status);CHKERRQ(ierr);
268869db28dcSHong Zhang       recv_rank[imdex] = recv_status.MPI_SOURCE;
268969db28dcSHong Zhang       /* allocate rbuf_a and rbuf_j; then post receives of rbuf_j */
269069db28dcSHong Zhang       ierr = PetscMalloc((rbuf_nz[imdex]+1)*sizeof(PetscScalar),&rbuf_a[imdex]);CHKERRQ(ierr);
269169db28dcSHong Zhang 
269269db28dcSHong Zhang       i = rowrange[recv_status.MPI_SOURCE+1] - rowrange[recv_status.MPI_SOURCE]; /* number of expected mat->i */
269369db28dcSHong Zhang       rbuf_nz[imdex] += i + 2;
269469db28dcSHong Zhang       ierr = PetscMalloc(rbuf_nz[imdex]*sizeof(PetscInt),&rbuf_j[imdex]);CHKERRQ(ierr);
269569db28dcSHong Zhang       ierr = MPI_Irecv(rbuf_j[imdex],rbuf_nz[imdex],MPIU_INT,recv_status.MPI_SOURCE,tag2,comm,r_waits2+imdex);CHKERRQ(ierr);
269669db28dcSHong Zhang       count--;
269769db28dcSHong Zhang     }
269869db28dcSHong Zhang     /* wait on sends of nzlocal */
269969db28dcSHong Zhang     if (nsends) {ierr = MPI_Waitall(nsends,s_waits1,send_status);CHKERRQ(ierr);}
270069db28dcSHong Zhang     /* send mat->i,j to others, and recv from other's */
270169db28dcSHong Zhang     /*------------------------------------------------*/
270269db28dcSHong Zhang     for (i=0; i<nsends; i++){
270369db28dcSHong Zhang       j = nzlocal + rowrange[rank+1] - rowrange[rank] + 1;
270469db28dcSHong Zhang       ierr = MPI_Isend(sbuf_j,j,MPIU_INT,send_rank[i],tag2,comm,s_waits2+i);CHKERRQ(ierr);
270569db28dcSHong Zhang     }
270669db28dcSHong Zhang     /* wait on receives of mat->i,j */
270769db28dcSHong Zhang     /*------------------------------*/
270869db28dcSHong Zhang     count = nrecvs;
270969db28dcSHong Zhang     while (count) {
271069db28dcSHong Zhang       ierr = MPI_Waitany(nrecvs,r_waits2,&imdex,&recv_status);CHKERRQ(ierr);
2711e32f2f54SBarry Smith       if (recv_rank[imdex] != recv_status.MPI_SOURCE) SETERRQ2(PETSC_COMM_SELF,1, "recv_rank %d != MPI_SOURCE %d",recv_rank[imdex],recv_status.MPI_SOURCE);
271269db28dcSHong Zhang       count--;
271369db28dcSHong Zhang     }
271469db28dcSHong Zhang     /* wait on sends of mat->i,j */
271569db28dcSHong Zhang     /*---------------------------*/
271669db28dcSHong Zhang     if (nsends) {
271769db28dcSHong Zhang       ierr = MPI_Waitall(nsends,s_waits2,send_status);CHKERRQ(ierr);
271869db28dcSHong Zhang     }
271969db28dcSHong Zhang   } /* endof if (reuse == MAT_INITIAL_MATRIX) */
272069db28dcSHong Zhang 
272169db28dcSHong Zhang   /* post receives, send and receive mat->a */
272269db28dcSHong Zhang   /*----------------------------------------*/
272369db28dcSHong Zhang   for (imdex=0; imdex<nrecvs; imdex++) {
272469db28dcSHong Zhang     ierr = MPI_Irecv(rbuf_a[imdex],rbuf_nz[imdex],MPIU_SCALAR,recv_rank[imdex],tag3,comm,r_waits3+imdex);CHKERRQ(ierr);
272569db28dcSHong Zhang   }
272669db28dcSHong Zhang   for (i=0; i<nsends; i++){
272769db28dcSHong Zhang     ierr = MPI_Isend(sbuf_a,nzlocal,MPIU_SCALAR,send_rank[i],tag3,comm,s_waits3+i);CHKERRQ(ierr);
272869db28dcSHong Zhang   }
272969db28dcSHong Zhang   count = nrecvs;
273069db28dcSHong Zhang   while (count) {
273169db28dcSHong Zhang     ierr = MPI_Waitany(nrecvs,r_waits3,&imdex,&recv_status);CHKERRQ(ierr);
2732e32f2f54SBarry Smith     if (recv_rank[imdex] != recv_status.MPI_SOURCE) SETERRQ2(PETSC_COMM_SELF,1, "recv_rank %d != MPI_SOURCE %d",recv_rank[imdex],recv_status.MPI_SOURCE);
273369db28dcSHong Zhang     count--;
273469db28dcSHong Zhang   }
273569db28dcSHong Zhang   if (nsends) {
273669db28dcSHong Zhang     ierr = MPI_Waitall(nsends,s_waits3,send_status);CHKERRQ(ierr);
273769db28dcSHong Zhang   }
273869db28dcSHong Zhang 
273969db28dcSHong Zhang   ierr = PetscFree2(s_waits3,send_status);CHKERRQ(ierr);
274069db28dcSHong Zhang 
274169db28dcSHong Zhang   /* create redundant matrix */
274269db28dcSHong Zhang   /*-------------------------*/
274369db28dcSHong Zhang   if (reuse == MAT_INITIAL_MATRIX){
274469db28dcSHong Zhang     /* compute rownz_max for preallocation */
274569db28dcSHong Zhang     for (imdex=0; imdex<nrecvs; imdex++){
274669db28dcSHong Zhang       j = rowrange[recv_rank[imdex]+1] - rowrange[recv_rank[imdex]];
274769db28dcSHong Zhang       rptr = rbuf_j[imdex];
274869db28dcSHong Zhang       for (i=0; i<j; i++){
274969db28dcSHong Zhang         ncols = rptr[i+1] - rptr[i];
275069db28dcSHong Zhang         if (rownz_max < ncols) rownz_max = ncols;
275169db28dcSHong Zhang       }
275269db28dcSHong Zhang     }
275369db28dcSHong Zhang 
275469db28dcSHong Zhang     ierr = MatCreate(subcomm,&C);CHKERRQ(ierr);
275569db28dcSHong Zhang     ierr = MatSetSizes(C,mlocal_sub,mlocal_sub,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
2756a2f3521dSMark F. Adams     ierr = MatSetBlockSizes(C,mat->rmap->bs,mat->cmap->bs); CHKERRQ(ierr);
275769db28dcSHong Zhang     ierr = MatSetFromOptions(C);CHKERRQ(ierr);
275869db28dcSHong Zhang     ierr = MatSeqAIJSetPreallocation(C,rownz_max,PETSC_NULL);CHKERRQ(ierr);
275969db28dcSHong Zhang     ierr = MatMPIAIJSetPreallocation(C,rownz_max,PETSC_NULL,rownz_max,PETSC_NULL);CHKERRQ(ierr);
276069db28dcSHong Zhang   } else {
276169db28dcSHong Zhang     C = *matredundant;
276269db28dcSHong Zhang   }
276369db28dcSHong Zhang 
276469db28dcSHong Zhang   /* insert local matrix entries */
276569db28dcSHong Zhang   rptr = sbuf_j;
276669db28dcSHong Zhang   cols = sbuf_j + rend-rstart + 1;
276769db28dcSHong Zhang   vals = sbuf_a;
276869db28dcSHong Zhang   for (i=0; i<rend-rstart; i++){
276969db28dcSHong Zhang     row   = i + rstart;
277069db28dcSHong Zhang     ncols = rptr[i+1] - rptr[i];
277169db28dcSHong Zhang     ierr = MatSetValues(C,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
277269db28dcSHong Zhang     vals += ncols;
277369db28dcSHong Zhang     cols += ncols;
277469db28dcSHong Zhang   }
277569db28dcSHong Zhang   /* insert received matrix entries */
277669db28dcSHong Zhang   for (imdex=0; imdex<nrecvs; imdex++){
277769db28dcSHong Zhang     rstart = rowrange[recv_rank[imdex]];
277869db28dcSHong Zhang     rend   = rowrange[recv_rank[imdex]+1];
277969db28dcSHong Zhang     rptr = rbuf_j[imdex];
278069db28dcSHong Zhang     cols = rbuf_j[imdex] + rend-rstart + 1;
278169db28dcSHong Zhang     vals = rbuf_a[imdex];
278269db28dcSHong Zhang     for (i=0; i<rend-rstart; i++){
278369db28dcSHong Zhang       row   = i + rstart;
278469db28dcSHong Zhang       ncols = rptr[i+1] - rptr[i];
278569db28dcSHong Zhang       ierr = MatSetValues(C,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
278669db28dcSHong Zhang       vals += ncols;
278769db28dcSHong Zhang       cols += ncols;
278869db28dcSHong Zhang     }
278969db28dcSHong Zhang   }
279069db28dcSHong Zhang   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
279169db28dcSHong Zhang   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
279269db28dcSHong Zhang   ierr = MatGetSize(C,&M,&N);CHKERRQ(ierr);
2793e32f2f54SBarry Smith   if (M != mat->rmap->N || N != mat->cmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"redundant mat size %d != input mat size %d",M,mat->rmap->N);
279469db28dcSHong Zhang   if (reuse == MAT_INITIAL_MATRIX) {
279569db28dcSHong Zhang     PetscContainer container;
279669db28dcSHong Zhang     *matredundant = C;
279769db28dcSHong Zhang     /* create a supporting struct and attach it to C for reuse */
279838f2d2fdSLisandro Dalcin     ierr = PetscNewLog(C,Mat_Redundant,&redund);CHKERRQ(ierr);
279969db28dcSHong Zhang     ierr = PetscContainerCreate(PETSC_COMM_SELF,&container);CHKERRQ(ierr);
280069db28dcSHong Zhang     ierr = PetscContainerSetPointer(container,redund);CHKERRQ(ierr);
280169db28dcSHong Zhang     ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_MatRedundant);CHKERRQ(ierr);
2802bf0cc555SLisandro Dalcin     ierr = PetscObjectCompose((PetscObject)C,"Mat_Redundant",(PetscObject)container);CHKERRQ(ierr);
2803bf0cc555SLisandro Dalcin     ierr = PetscContainerDestroy(&container);CHKERRQ(ierr);
280469db28dcSHong Zhang 
280569db28dcSHong Zhang     redund->nzlocal = nzlocal;
280669db28dcSHong Zhang     redund->nsends  = nsends;
280769db28dcSHong Zhang     redund->nrecvs  = nrecvs;
280869db28dcSHong Zhang     redund->send_rank = send_rank;
28091d79065fSBarry Smith     redund->recv_rank = recv_rank;
281069db28dcSHong Zhang     redund->sbuf_nz = sbuf_nz;
28111d79065fSBarry Smith     redund->rbuf_nz = rbuf_nz;
281269db28dcSHong Zhang     redund->sbuf_j  = sbuf_j;
281369db28dcSHong Zhang     redund->sbuf_a  = sbuf_a;
281469db28dcSHong Zhang     redund->rbuf_j  = rbuf_j;
281569db28dcSHong Zhang     redund->rbuf_a  = rbuf_a;
281669db28dcSHong Zhang 
2817bf0cc555SLisandro Dalcin     redund->Destroy = C->ops->destroy;
281869db28dcSHong Zhang     C->ops->destroy = MatDestroy_MatRedundant;
281969db28dcSHong Zhang   }
282069db28dcSHong Zhang   PetscFunctionReturn(0);
282169db28dcSHong Zhang }
282269db28dcSHong Zhang 
282303bc72f1SMatthew Knepley #undef __FUNCT__
2824c91732d9SHong Zhang #define __FUNCT__ "MatGetRowMaxAbs_MPIAIJ"
2825c91732d9SHong Zhang PetscErrorCode MatGetRowMaxAbs_MPIAIJ(Mat A, Vec v, PetscInt idx[])
2826c91732d9SHong Zhang {
2827c91732d9SHong Zhang   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
2828c91732d9SHong Zhang   PetscErrorCode ierr;
2829c91732d9SHong Zhang   PetscInt       i,*idxb = 0;
2830c91732d9SHong Zhang   PetscScalar    *va,*vb;
2831c91732d9SHong Zhang   Vec            vtmp;
2832c91732d9SHong Zhang 
2833c91732d9SHong Zhang   PetscFunctionBegin;
2834c91732d9SHong Zhang   ierr = MatGetRowMaxAbs(a->A,v,idx);CHKERRQ(ierr);
2835c91732d9SHong Zhang   ierr = VecGetArray(v,&va);CHKERRQ(ierr);
2836c91732d9SHong Zhang   if (idx) {
2837192daf7cSBarry Smith     for (i=0; i<A->rmap->n; i++) {
2838d0f46423SBarry Smith       if (PetscAbsScalar(va[i])) idx[i] += A->cmap->rstart;
2839c91732d9SHong Zhang     }
2840c91732d9SHong Zhang   }
2841c91732d9SHong Zhang 
2842d0f46423SBarry Smith   ierr = VecCreateSeq(PETSC_COMM_SELF,A->rmap->n,&vtmp);CHKERRQ(ierr);
2843c91732d9SHong Zhang   if (idx) {
2844d0f46423SBarry Smith     ierr = PetscMalloc(A->rmap->n*sizeof(PetscInt),&idxb);CHKERRQ(ierr);
2845c91732d9SHong Zhang   }
2846c91732d9SHong Zhang   ierr = MatGetRowMaxAbs(a->B,vtmp,idxb);CHKERRQ(ierr);
2847c91732d9SHong Zhang   ierr = VecGetArray(vtmp,&vb);CHKERRQ(ierr);
2848c91732d9SHong Zhang 
2849d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++){
2850c91732d9SHong Zhang     if (PetscAbsScalar(va[i]) < PetscAbsScalar(vb[i])) {
2851c91732d9SHong Zhang       va[i] = vb[i];
2852c91732d9SHong Zhang       if (idx) idx[i] = a->garray[idxb[i]];
2853c91732d9SHong Zhang     }
2854c91732d9SHong Zhang   }
2855c91732d9SHong Zhang 
2856c91732d9SHong Zhang   ierr = VecRestoreArray(v,&va);CHKERRQ(ierr);
2857c91732d9SHong Zhang   ierr = VecRestoreArray(vtmp,&vb);CHKERRQ(ierr);
2858c91732d9SHong Zhang   ierr = PetscFree(idxb);CHKERRQ(ierr);
28596bf464f9SBarry Smith   ierr = VecDestroy(&vtmp);CHKERRQ(ierr);
2860c91732d9SHong Zhang   PetscFunctionReturn(0);
2861c91732d9SHong Zhang }
2862c91732d9SHong Zhang 
2863c91732d9SHong Zhang #undef __FUNCT__
2864c87e5d42SMatthew Knepley #define __FUNCT__ "MatGetRowMinAbs_MPIAIJ"
2865c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_MPIAIJ(Mat A, Vec v, PetscInt idx[])
2866c87e5d42SMatthew Knepley {
2867c87e5d42SMatthew Knepley   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
2868c87e5d42SMatthew Knepley   PetscErrorCode ierr;
2869c87e5d42SMatthew Knepley   PetscInt       i,*idxb = 0;
2870c87e5d42SMatthew Knepley   PetscScalar    *va,*vb;
2871c87e5d42SMatthew Knepley   Vec            vtmp;
2872c87e5d42SMatthew Knepley 
2873c87e5d42SMatthew Knepley   PetscFunctionBegin;
2874c87e5d42SMatthew Knepley   ierr = MatGetRowMinAbs(a->A,v,idx);CHKERRQ(ierr);
2875c87e5d42SMatthew Knepley   ierr = VecGetArray(v,&va);CHKERRQ(ierr);
2876c87e5d42SMatthew Knepley   if (idx) {
2877c87e5d42SMatthew Knepley     for (i=0; i<A->cmap->n; i++) {
2878c87e5d42SMatthew Knepley       if (PetscAbsScalar(va[i])) idx[i] += A->cmap->rstart;
2879c87e5d42SMatthew Knepley     }
2880c87e5d42SMatthew Knepley   }
2881c87e5d42SMatthew Knepley 
2882c87e5d42SMatthew Knepley   ierr = VecCreateSeq(PETSC_COMM_SELF,A->rmap->n,&vtmp);CHKERRQ(ierr);
2883c87e5d42SMatthew Knepley   if (idx) {
2884c87e5d42SMatthew Knepley     ierr = PetscMalloc(A->rmap->n*sizeof(PetscInt),&idxb);CHKERRQ(ierr);
2885c87e5d42SMatthew Knepley   }
2886c87e5d42SMatthew Knepley   ierr = MatGetRowMinAbs(a->B,vtmp,idxb);CHKERRQ(ierr);
2887c87e5d42SMatthew Knepley   ierr = VecGetArray(vtmp,&vb);CHKERRQ(ierr);
2888c87e5d42SMatthew Knepley 
2889c87e5d42SMatthew Knepley   for (i=0; i<A->rmap->n; i++){
2890c87e5d42SMatthew Knepley     if (PetscAbsScalar(va[i]) > PetscAbsScalar(vb[i])) {
2891c87e5d42SMatthew Knepley       va[i] = vb[i];
2892c87e5d42SMatthew Knepley       if (idx) idx[i] = a->garray[idxb[i]];
2893c87e5d42SMatthew Knepley     }
2894c87e5d42SMatthew Knepley   }
2895c87e5d42SMatthew Knepley 
2896c87e5d42SMatthew Knepley   ierr = VecRestoreArray(v,&va);CHKERRQ(ierr);
2897c87e5d42SMatthew Knepley   ierr = VecRestoreArray(vtmp,&vb);CHKERRQ(ierr);
2898c87e5d42SMatthew Knepley   ierr = PetscFree(idxb);CHKERRQ(ierr);
28996bf464f9SBarry Smith   ierr = VecDestroy(&vtmp);CHKERRQ(ierr);
2900c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
2901c87e5d42SMatthew Knepley }
2902c87e5d42SMatthew Knepley 
2903c87e5d42SMatthew Knepley #undef __FUNCT__
290403bc72f1SMatthew Knepley #define __FUNCT__ "MatGetRowMin_MPIAIJ"
290503bc72f1SMatthew Knepley PetscErrorCode MatGetRowMin_MPIAIJ(Mat A, Vec v, PetscInt idx[])
290603bc72f1SMatthew Knepley {
290703bc72f1SMatthew Knepley   Mat_MPIAIJ    *mat    = (Mat_MPIAIJ *) A->data;
2908d0f46423SBarry Smith   PetscInt       n      = A->rmap->n;
2909d0f46423SBarry Smith   PetscInt       cstart = A->cmap->rstart;
291003bc72f1SMatthew Knepley   PetscInt      *cmap   = mat->garray;
291103bc72f1SMatthew Knepley   PetscInt      *diagIdx, *offdiagIdx;
291203bc72f1SMatthew Knepley   Vec            diagV, offdiagV;
291303bc72f1SMatthew Knepley   PetscScalar   *a, *diagA, *offdiagA;
291403bc72f1SMatthew Knepley   PetscInt       r;
291503bc72f1SMatthew Knepley   PetscErrorCode ierr;
291603bc72f1SMatthew Knepley 
291703bc72f1SMatthew Knepley   PetscFunctionBegin;
291803bc72f1SMatthew Knepley   ierr = PetscMalloc2(n,PetscInt,&diagIdx,n,PetscInt,&offdiagIdx);CHKERRQ(ierr);
2919e64afeacSLisandro Dalcin   ierr = VecCreateSeq(((PetscObject)A)->comm, n, &diagV);CHKERRQ(ierr);
2920e64afeacSLisandro Dalcin   ierr = VecCreateSeq(((PetscObject)A)->comm, n, &offdiagV);CHKERRQ(ierr);
292103bc72f1SMatthew Knepley   ierr = MatGetRowMin(mat->A, diagV,    diagIdx);CHKERRQ(ierr);
292203bc72f1SMatthew Knepley   ierr = MatGetRowMin(mat->B, offdiagV, offdiagIdx);CHKERRQ(ierr);
292303bc72f1SMatthew Knepley   ierr = VecGetArray(v,        &a);CHKERRQ(ierr);
292403bc72f1SMatthew Knepley   ierr = VecGetArray(diagV,    &diagA);CHKERRQ(ierr);
292503bc72f1SMatthew Knepley   ierr = VecGetArray(offdiagV, &offdiagA);CHKERRQ(ierr);
292603bc72f1SMatthew Knepley   for(r = 0; r < n; ++r) {
2927028cd4eaSSatish Balay     if (PetscAbsScalar(diagA[r]) <= PetscAbsScalar(offdiagA[r])) {
292803bc72f1SMatthew Knepley       a[r]   = diagA[r];
292903bc72f1SMatthew Knepley       idx[r] = cstart + diagIdx[r];
293003bc72f1SMatthew Knepley     } else {
293103bc72f1SMatthew Knepley       a[r]   = offdiagA[r];
293203bc72f1SMatthew Knepley       idx[r] = cmap[offdiagIdx[r]];
293303bc72f1SMatthew Knepley     }
293403bc72f1SMatthew Knepley   }
293503bc72f1SMatthew Knepley   ierr = VecRestoreArray(v,        &a);CHKERRQ(ierr);
293603bc72f1SMatthew Knepley   ierr = VecRestoreArray(diagV,    &diagA);CHKERRQ(ierr);
293703bc72f1SMatthew Knepley   ierr = VecRestoreArray(offdiagV, &offdiagA);CHKERRQ(ierr);
29386bf464f9SBarry Smith   ierr = VecDestroy(&diagV);CHKERRQ(ierr);
29396bf464f9SBarry Smith   ierr = VecDestroy(&offdiagV);CHKERRQ(ierr);
294003bc72f1SMatthew Knepley   ierr = PetscFree2(diagIdx, offdiagIdx);CHKERRQ(ierr);
294103bc72f1SMatthew Knepley   PetscFunctionReturn(0);
294203bc72f1SMatthew Knepley }
294303bc72f1SMatthew Knepley 
29445494a064SHong Zhang #undef __FUNCT__
2945c87e5d42SMatthew Knepley #define __FUNCT__ "MatGetRowMax_MPIAIJ"
2946c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMax_MPIAIJ(Mat A, Vec v, PetscInt idx[])
2947c87e5d42SMatthew Knepley {
2948c87e5d42SMatthew Knepley   Mat_MPIAIJ    *mat    = (Mat_MPIAIJ *) A->data;
2949c87e5d42SMatthew Knepley   PetscInt       n      = A->rmap->n;
2950c87e5d42SMatthew Knepley   PetscInt       cstart = A->cmap->rstart;
2951c87e5d42SMatthew Knepley   PetscInt      *cmap   = mat->garray;
2952c87e5d42SMatthew Knepley   PetscInt      *diagIdx, *offdiagIdx;
2953c87e5d42SMatthew Knepley   Vec            diagV, offdiagV;
2954c87e5d42SMatthew Knepley   PetscScalar   *a, *diagA, *offdiagA;
2955c87e5d42SMatthew Knepley   PetscInt       r;
2956c87e5d42SMatthew Knepley   PetscErrorCode ierr;
2957c87e5d42SMatthew Knepley 
2958c87e5d42SMatthew Knepley   PetscFunctionBegin;
2959c87e5d42SMatthew Knepley   ierr = PetscMalloc2(n,PetscInt,&diagIdx,n,PetscInt,&offdiagIdx);CHKERRQ(ierr);
2960c87e5d42SMatthew Knepley   ierr = VecCreateSeq(((PetscObject)A)->comm, n, &diagV);CHKERRQ(ierr);
2961c87e5d42SMatthew Knepley   ierr = VecCreateSeq(((PetscObject)A)->comm, n, &offdiagV);CHKERRQ(ierr);
2962c87e5d42SMatthew Knepley   ierr = MatGetRowMax(mat->A, diagV,    diagIdx);CHKERRQ(ierr);
2963c87e5d42SMatthew Knepley   ierr = MatGetRowMax(mat->B, offdiagV, offdiagIdx);CHKERRQ(ierr);
2964c87e5d42SMatthew Knepley   ierr = VecGetArray(v,        &a);CHKERRQ(ierr);
2965c87e5d42SMatthew Knepley   ierr = VecGetArray(diagV,    &diagA);CHKERRQ(ierr);
2966c87e5d42SMatthew Knepley   ierr = VecGetArray(offdiagV, &offdiagA);CHKERRQ(ierr);
2967c87e5d42SMatthew Knepley   for(r = 0; r < n; ++r) {
2968c87e5d42SMatthew Knepley     if (PetscAbsScalar(diagA[r]) >= PetscAbsScalar(offdiagA[r])) {
2969c87e5d42SMatthew Knepley       a[r]   = diagA[r];
2970c87e5d42SMatthew Knepley       idx[r] = cstart + diagIdx[r];
2971c87e5d42SMatthew Knepley     } else {
2972c87e5d42SMatthew Knepley       a[r]   = offdiagA[r];
2973c87e5d42SMatthew Knepley       idx[r] = cmap[offdiagIdx[r]];
2974c87e5d42SMatthew Knepley     }
2975c87e5d42SMatthew Knepley   }
2976c87e5d42SMatthew Knepley   ierr = VecRestoreArray(v,        &a);CHKERRQ(ierr);
2977c87e5d42SMatthew Knepley   ierr = VecRestoreArray(diagV,    &diagA);CHKERRQ(ierr);
2978c87e5d42SMatthew Knepley   ierr = VecRestoreArray(offdiagV, &offdiagA);CHKERRQ(ierr);
29796bf464f9SBarry Smith   ierr = VecDestroy(&diagV);CHKERRQ(ierr);
29806bf464f9SBarry Smith   ierr = VecDestroy(&offdiagV);CHKERRQ(ierr);
2981c87e5d42SMatthew Knepley   ierr = PetscFree2(diagIdx, offdiagIdx);CHKERRQ(ierr);
2982c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
2983c87e5d42SMatthew Knepley }
2984c87e5d42SMatthew Knepley 
2985c87e5d42SMatthew Knepley #undef __FUNCT__
2986d1adec66SJed Brown #define __FUNCT__ "MatGetSeqNonzeroStructure_MPIAIJ"
2987d1adec66SJed Brown PetscErrorCode MatGetSeqNonzeroStructure_MPIAIJ(Mat mat,Mat *newmat)
29885494a064SHong Zhang {
29895494a064SHong Zhang   PetscErrorCode ierr;
2990f6d58c54SBarry Smith   Mat            *dummy;
29915494a064SHong Zhang 
29925494a064SHong Zhang   PetscFunctionBegin;
2993f6d58c54SBarry Smith   ierr = MatGetSubMatrix_MPIAIJ_All(mat,MAT_DO_NOT_GET_VALUES,MAT_INITIAL_MATRIX,&dummy);CHKERRQ(ierr);
2994f6d58c54SBarry Smith   *newmat = *dummy;
2995f6d58c54SBarry Smith   ierr = PetscFree(dummy);CHKERRQ(ierr);
29965494a064SHong Zhang   PetscFunctionReturn(0);
29975494a064SHong Zhang }
29985494a064SHong Zhang 
29997087cfbeSBarry Smith extern PetscErrorCode  MatFDColoringApply_AIJ(Mat,MatFDColoring,Vec,MatStructure*,void*);
3000bbead8a2SBarry Smith 
3001bbead8a2SBarry Smith #undef __FUNCT__
3002bbead8a2SBarry Smith #define __FUNCT__ "MatInvertBlockDiagonal_MPIAIJ"
3003713ccfa9SJed Brown PetscErrorCode  MatInvertBlockDiagonal_MPIAIJ(Mat A,const PetscScalar **values)
3004bbead8a2SBarry Smith {
3005bbead8a2SBarry Smith   Mat_MPIAIJ    *a = (Mat_MPIAIJ*) A->data;
3006bbead8a2SBarry Smith   PetscErrorCode ierr;
3007bbead8a2SBarry Smith 
3008bbead8a2SBarry Smith   PetscFunctionBegin;
3009bbead8a2SBarry Smith   ierr = MatInvertBlockDiagonal(a->A,values);CHKERRQ(ierr);
3010bbead8a2SBarry Smith   PetscFunctionReturn(0);
3011bbead8a2SBarry Smith }
3012bbead8a2SBarry Smith 
3013*73a71a0fSBarry Smith #undef __FUNCT__
3014*73a71a0fSBarry Smith #define __FUNCT__ "MatSetRandom_MPIAIJ"
3015*73a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_MPIAIJ(Mat x,PetscRandom rctx)
3016*73a71a0fSBarry Smith {
3017*73a71a0fSBarry Smith   PetscErrorCode ierr;
3018*73a71a0fSBarry Smith   Mat_MPIAIJ     *aij = (Mat_MPIAIJ*)x->data;
3019*73a71a0fSBarry Smith 
3020*73a71a0fSBarry Smith   PetscFunctionBegin;
3021*73a71a0fSBarry Smith   ierr = MatSetRandom(aij->A,rctx);CHKERRQ(ierr);
3022*73a71a0fSBarry Smith   ierr = MatSetRandom(aij->B,rctx);CHKERRQ(ierr);
3023*73a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3024*73a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3025*73a71a0fSBarry Smith   PetscFunctionReturn(0);
3026*73a71a0fSBarry Smith }
3027bbead8a2SBarry Smith 
30288a729477SBarry Smith /* -------------------------------------------------------------------*/
3029cda55fadSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_MPIAIJ,
3030cda55fadSBarry Smith        MatGetRow_MPIAIJ,
3031cda55fadSBarry Smith        MatRestoreRow_MPIAIJ,
3032cda55fadSBarry Smith        MatMult_MPIAIJ,
303397304618SKris Buschelman /* 4*/ MatMultAdd_MPIAIJ,
30347c922b88SBarry Smith        MatMultTranspose_MPIAIJ,
30357c922b88SBarry Smith        MatMultTransposeAdd_MPIAIJ,
3036103bf8bdSMatthew Knepley #ifdef PETSC_HAVE_PBGL
3037103bf8bdSMatthew Knepley        MatSolve_MPIAIJ,
3038103bf8bdSMatthew Knepley #else
3039cda55fadSBarry Smith        0,
3040103bf8bdSMatthew Knepley #endif
3041cda55fadSBarry Smith        0,
3042cda55fadSBarry Smith        0,
304397304618SKris Buschelman /*10*/ 0,
3044cda55fadSBarry Smith        0,
3045cda55fadSBarry Smith        0,
304641f059aeSBarry Smith        MatSOR_MPIAIJ,
3047b7c46309SBarry Smith        MatTranspose_MPIAIJ,
304897304618SKris Buschelman /*15*/ MatGetInfo_MPIAIJ,
3049cda55fadSBarry Smith        MatEqual_MPIAIJ,
3050cda55fadSBarry Smith        MatGetDiagonal_MPIAIJ,
3051cda55fadSBarry Smith        MatDiagonalScale_MPIAIJ,
3052cda55fadSBarry Smith        MatNorm_MPIAIJ,
305397304618SKris Buschelman /*20*/ MatAssemblyBegin_MPIAIJ,
3054cda55fadSBarry Smith        MatAssemblyEnd_MPIAIJ,
3055cda55fadSBarry Smith        MatSetOption_MPIAIJ,
3056cda55fadSBarry Smith        MatZeroEntries_MPIAIJ,
3057d519adbfSMatthew Knepley /*24*/ MatZeroRows_MPIAIJ,
3058cda55fadSBarry Smith        0,
3059103bf8bdSMatthew Knepley #ifdef PETSC_HAVE_PBGL
3060719d5645SBarry Smith        0,
3061103bf8bdSMatthew Knepley #else
3062cda55fadSBarry Smith        0,
3063103bf8bdSMatthew Knepley #endif
3064cda55fadSBarry Smith        0,
3065cda55fadSBarry Smith        0,
30664994cf47SJed Brown /*29*/ MatSetUp_MPIAIJ,
3067103bf8bdSMatthew Knepley #ifdef PETSC_HAVE_PBGL
3068719d5645SBarry Smith        0,
3069103bf8bdSMatthew Knepley #else
3070cda55fadSBarry Smith        0,
3071103bf8bdSMatthew Knepley #endif
3072cda55fadSBarry Smith        0,
3073cda55fadSBarry Smith        0,
3074cda55fadSBarry Smith        0,
3075d519adbfSMatthew Knepley /*34*/ MatDuplicate_MPIAIJ,
3076cda55fadSBarry Smith        0,
3077cda55fadSBarry Smith        0,
3078cda55fadSBarry Smith        0,
3079cda55fadSBarry Smith        0,
3080d519adbfSMatthew Knepley /*39*/ MatAXPY_MPIAIJ,
3081cda55fadSBarry Smith        MatGetSubMatrices_MPIAIJ,
3082cda55fadSBarry Smith        MatIncreaseOverlap_MPIAIJ,
3083cda55fadSBarry Smith        MatGetValues_MPIAIJ,
3084cb5b572fSBarry Smith        MatCopy_MPIAIJ,
3085d519adbfSMatthew Knepley /*44*/ MatGetRowMax_MPIAIJ,
3086cda55fadSBarry Smith        MatScale_MPIAIJ,
3087cda55fadSBarry Smith        0,
3088cda55fadSBarry Smith        0,
3089564f14d6SBarry Smith        MatZeroRowsColumns_MPIAIJ,
3090*73a71a0fSBarry Smith /*49*/ MatSetRandom_MPIAIJ,
3091cda55fadSBarry Smith        0,
3092cda55fadSBarry Smith        0,
3093cda55fadSBarry Smith        0,
3094cda55fadSBarry Smith        0,
3095d519adbfSMatthew Knepley /*54*/ MatFDColoringCreate_MPIAIJ,
3096cda55fadSBarry Smith        0,
3097cda55fadSBarry Smith        MatSetUnfactored_MPIAIJ,
309829dcf524SDmitry Karpeev        0, /* MatPermute_MPIAIJ, impl currently broken */
3099cda55fadSBarry Smith        0,
3100d519adbfSMatthew Knepley /*59*/ MatGetSubMatrix_MPIAIJ,
3101e03a110bSBarry Smith        MatDestroy_MPIAIJ,
3102e03a110bSBarry Smith        MatView_MPIAIJ,
3103357abbc8SBarry Smith        0,
3104a2243be0SBarry Smith        0,
3105d519adbfSMatthew Knepley /*64*/ 0,
3106a2243be0SBarry Smith        0,
3107a2243be0SBarry Smith        0,
3108a2243be0SBarry Smith        0,
3109a2243be0SBarry Smith        0,
3110d519adbfSMatthew Knepley /*69*/ MatGetRowMaxAbs_MPIAIJ,
3111c87e5d42SMatthew Knepley        MatGetRowMinAbs_MPIAIJ,
3112a2243be0SBarry Smith        0,
3113a2243be0SBarry Smith        MatSetColoring_MPIAIJ,
3114dcf5cc72SBarry Smith #if defined(PETSC_HAVE_ADIC)
3115779c1a83SBarry Smith        MatSetValuesAdic_MPIAIJ,
3116dcf5cc72SBarry Smith #else
3117dcf5cc72SBarry Smith        0,
3118dcf5cc72SBarry Smith #endif
311997304618SKris Buschelman        MatSetValuesAdifor_MPIAIJ,
31203acb8795SBarry Smith /*75*/ MatFDColoringApply_AIJ,
312197304618SKris Buschelman        0,
312297304618SKris Buschelman        0,
312397304618SKris Buschelman        0,
3124f1f41ecbSJed Brown        MatFindZeroDiagonals_MPIAIJ,
312597304618SKris Buschelman /*80*/ 0,
312697304618SKris Buschelman        0,
312797304618SKris Buschelman        0,
31285bba2384SShri Abhyankar /*83*/ MatLoad_MPIAIJ,
31296284ec50SHong Zhang        0,
31306284ec50SHong Zhang        0,
31316284ec50SHong Zhang        0,
31326284ec50SHong Zhang        0,
3133865e5f61SKris Buschelman        0,
3134d519adbfSMatthew Knepley /*89*/ MatMatMult_MPIAIJ_MPIAIJ,
313526be0446SHong Zhang        MatMatMultSymbolic_MPIAIJ_MPIAIJ,
313626be0446SHong Zhang        MatMatMultNumeric_MPIAIJ_MPIAIJ,
31377a7894deSKris Buschelman        MatPtAP_Basic,
31387a7894deSKris Buschelman        MatPtAPSymbolic_MPIAIJ,
3139d519adbfSMatthew Knepley /*94*/ MatPtAPNumeric_MPIAIJ,
31407a7894deSKris Buschelman        0,
31417a7894deSKris Buschelman        0,
31427a7894deSKris Buschelman        0,
31437a7894deSKris Buschelman        0,
3144d519adbfSMatthew Knepley /*99*/ 0,
3145865e5f61SKris Buschelman        MatPtAPSymbolic_MPIAIJ_MPIAIJ,
31467a7894deSKris Buschelman        MatPtAPNumeric_MPIAIJ_MPIAIJ,
31472fd7e33dSBarry Smith        MatConjugate_MPIAIJ,
31482fd7e33dSBarry Smith        0,
3149d519adbfSMatthew Knepley /*104*/MatSetValuesRow_MPIAIJ,
315099cafbc1SBarry Smith        MatRealPart_MPIAIJ,
315169db28dcSHong Zhang        MatImaginaryPart_MPIAIJ,
315269db28dcSHong Zhang        0,
315369db28dcSHong Zhang        0,
3154d519adbfSMatthew Knepley /*109*/0,
315503bc72f1SMatthew Knepley        MatGetRedundantMatrix_MPIAIJ,
31565494a064SHong Zhang        MatGetRowMin_MPIAIJ,
31575494a064SHong Zhang        0,
31585494a064SHong Zhang        0,
3159d1adec66SJed Brown /*114*/MatGetSeqNonzeroStructure_MPIAIJ,
3160bd0c2dcbSBarry Smith        0,
3161bd0c2dcbSBarry Smith        0,
3162bd0c2dcbSBarry Smith        0,
3163bd0c2dcbSBarry Smith        0,
31648fb81238SShri Abhyankar /*119*/0,
31658fb81238SShri Abhyankar        0,
31668fb81238SShri Abhyankar        0,
3167d6037b41SHong Zhang        0,
3168b9614d88SDmitry Karpeev        MatGetMultiProcBlock_MPIAIJ,
3169f2c98031SJed Brown /*124*/MatFindNonzeroRows_MPIAIJ,
31700716a85fSBarry Smith        MatGetColumnNorms_MPIAIJ,
3171bbead8a2SBarry Smith        MatInvertBlockDiagonal_MPIAIJ,
3172b9614d88SDmitry Karpeev        0,
317337868618SMatthew G Knepley        MatGetSubMatricesParallel_MPIAIJ,
3174187b3c17SHong Zhang /*129*/0,
3175187b3c17SHong Zhang        MatTransposeMatMult_MPIAIJ_MPIAIJ,
3176187b3c17SHong Zhang        MatTransposeMatMultSymbolic_MPIAIJ_MPIAIJ,
3177187b3c17SHong Zhang        MatTransposeMatMultNumeric_MPIAIJ_MPIAIJ,
3178187b3c17SHong Zhang        0,
3179187b3c17SHong Zhang /*134*/0,
3180187b3c17SHong Zhang        0,
3181187b3c17SHong Zhang        0,
3182187b3c17SHong Zhang        0,
3183187b3c17SHong Zhang        0
3184bd0c2dcbSBarry Smith };
318536ce4990SBarry Smith 
31862e8a6d31SBarry Smith /* ----------------------------------------------------------------------------------------*/
31872e8a6d31SBarry Smith 
3188fb2e594dSBarry Smith EXTERN_C_BEGIN
31894a2ae208SSatish Balay #undef __FUNCT__
31904a2ae208SSatish Balay #define __FUNCT__ "MatStoreValues_MPIAIJ"
31917087cfbeSBarry Smith PetscErrorCode  MatStoreValues_MPIAIJ(Mat mat)
31922e8a6d31SBarry Smith {
31932e8a6d31SBarry Smith   Mat_MPIAIJ     *aij = (Mat_MPIAIJ *)mat->data;
3194dfbe8321SBarry Smith   PetscErrorCode ierr;
31952e8a6d31SBarry Smith 
31962e8a6d31SBarry Smith   PetscFunctionBegin;
31972e8a6d31SBarry Smith   ierr = MatStoreValues(aij->A);CHKERRQ(ierr);
31982e8a6d31SBarry Smith   ierr = MatStoreValues(aij->B);CHKERRQ(ierr);
31992e8a6d31SBarry Smith   PetscFunctionReturn(0);
32002e8a6d31SBarry Smith }
3201fb2e594dSBarry Smith EXTERN_C_END
32022e8a6d31SBarry Smith 
3203fb2e594dSBarry Smith EXTERN_C_BEGIN
32044a2ae208SSatish Balay #undef __FUNCT__
32054a2ae208SSatish Balay #define __FUNCT__ "MatRetrieveValues_MPIAIJ"
32067087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_MPIAIJ(Mat mat)
32072e8a6d31SBarry Smith {
32082e8a6d31SBarry Smith   Mat_MPIAIJ     *aij = (Mat_MPIAIJ *)mat->data;
3209dfbe8321SBarry Smith   PetscErrorCode ierr;
32102e8a6d31SBarry Smith 
32112e8a6d31SBarry Smith   PetscFunctionBegin;
32122e8a6d31SBarry Smith   ierr = MatRetrieveValues(aij->A);CHKERRQ(ierr);
32132e8a6d31SBarry Smith   ierr = MatRetrieveValues(aij->B);CHKERRQ(ierr);
32142e8a6d31SBarry Smith   PetscFunctionReturn(0);
32152e8a6d31SBarry Smith }
3216fb2e594dSBarry Smith EXTERN_C_END
32178a729477SBarry Smith 
321827508adbSBarry Smith EXTERN_C_BEGIN
32194a2ae208SSatish Balay #undef __FUNCT__
3220a23d5eceSKris Buschelman #define __FUNCT__ "MatMPIAIJSetPreallocation_MPIAIJ"
32217087cfbeSBarry Smith PetscErrorCode  MatMPIAIJSetPreallocation_MPIAIJ(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
3222a23d5eceSKris Buschelman {
3223a23d5eceSKris Buschelman   Mat_MPIAIJ     *b;
3224dfbe8321SBarry Smith   PetscErrorCode ierr;
3225b1d57f15SBarry Smith   PetscInt       i;
32262576faa2SJed Brown   PetscBool      d_realalloc = PETSC_FALSE,o_realalloc = PETSC_FALSE;
3227a23d5eceSKris Buschelman 
3228a23d5eceSKris Buschelman   PetscFunctionBegin;
32292576faa2SJed Brown   if (d_nz >= 0 || d_nnz) d_realalloc = PETSC_TRUE;
32302576faa2SJed Brown   if (o_nz >= 0 || o_nnz) o_realalloc = PETSC_TRUE;
3231a23d5eceSKris Buschelman   if (d_nz == PETSC_DEFAULT || d_nz == PETSC_DECIDE) d_nz = 5;
3232a23d5eceSKris Buschelman   if (o_nz == PETSC_DEFAULT || o_nz == PETSC_DECIDE) o_nz = 2;
3233e32f2f54SBarry Smith   if (d_nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"d_nz cannot be less than 0: value %D",d_nz);
3234e32f2f54SBarry Smith   if (o_nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"o_nz cannot be less than 0: value %D",o_nz);
3235899cda47SBarry Smith 
323626283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
323726283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
3238a23d5eceSKris Buschelman   if (d_nnz) {
3239d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
3240e32f2f54SBarry Smith       if (d_nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"d_nnz cannot be less than 0: local row %D value %D",i,d_nnz[i]);
3241a23d5eceSKris Buschelman     }
3242a23d5eceSKris Buschelman   }
3243a23d5eceSKris Buschelman   if (o_nnz) {
3244d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
3245e32f2f54SBarry Smith       if (o_nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"o_nnz cannot be less than 0: local row %D value %D",i,o_nnz[i]);
3246a23d5eceSKris Buschelman     }
3247a23d5eceSKris Buschelman   }
3248a23d5eceSKris Buschelman   b = (Mat_MPIAIJ*)B->data;
3249899cda47SBarry Smith 
3250526dfc15SBarry Smith   if (!B->preallocated) {
3251899cda47SBarry Smith     /* Explicitly create 2 MATSEQAIJ matrices. */
3252899cda47SBarry Smith     ierr = MatCreate(PETSC_COMM_SELF,&b->A);CHKERRQ(ierr);
3253d0f46423SBarry Smith     ierr = MatSetSizes(b->A,B->rmap->n,B->cmap->n,B->rmap->n,B->cmap->n);CHKERRQ(ierr);
3254f9e9af59SJed Brown     ierr = MatSetBlockSizes(b->A,B->rmap->bs,B->cmap->bs);CHKERRQ(ierr);
3255899cda47SBarry Smith     ierr = MatSetType(b->A,MATSEQAIJ);CHKERRQ(ierr);
3256899cda47SBarry Smith     ierr = PetscLogObjectParent(B,b->A);CHKERRQ(ierr);
3257899cda47SBarry Smith     ierr = MatCreate(PETSC_COMM_SELF,&b->B);CHKERRQ(ierr);
3258d0f46423SBarry Smith     ierr = MatSetSizes(b->B,B->rmap->n,B->cmap->N,B->rmap->n,B->cmap->N);CHKERRQ(ierr);
3259f9e9af59SJed Brown     ierr = MatSetBlockSizes(b->B,B->rmap->bs,B->cmap->bs);CHKERRQ(ierr);
3260899cda47SBarry Smith     ierr = MatSetType(b->B,MATSEQAIJ);CHKERRQ(ierr);
3261899cda47SBarry Smith     ierr = PetscLogObjectParent(B,b->B);CHKERRQ(ierr);
3262526dfc15SBarry Smith   }
3263899cda47SBarry Smith 
3264c60e587dSKris Buschelman   ierr = MatSeqAIJSetPreallocation(b->A,d_nz,d_nnz);CHKERRQ(ierr);
3265c60e587dSKris Buschelman   ierr = MatSeqAIJSetPreallocation(b->B,o_nz,o_nnz);CHKERRQ(ierr);
32662576faa2SJed Brown   /* Do not error if the user did not give real preallocation information. Ugly because this would overwrite a previous user call to MatSetOption(). */
32672576faa2SJed Brown   if (!d_realalloc) {ierr = MatSetOption(b->A,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);}
32682576faa2SJed Brown   if (!o_realalloc) {ierr = MatSetOption(b->B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);}
3269526dfc15SBarry Smith   B->preallocated = PETSC_TRUE;
3270a23d5eceSKris Buschelman   PetscFunctionReturn(0);
3271a23d5eceSKris Buschelman }
3272a23d5eceSKris Buschelman EXTERN_C_END
3273a23d5eceSKris Buschelman 
32744a2ae208SSatish Balay #undef __FUNCT__
32754a2ae208SSatish Balay #define __FUNCT__ "MatDuplicate_MPIAIJ"
3276dfbe8321SBarry Smith PetscErrorCode MatDuplicate_MPIAIJ(Mat matin,MatDuplicateOption cpvalues,Mat *newmat)
3277d6dfbf8fSBarry Smith {
3278d6dfbf8fSBarry Smith   Mat            mat;
3279416022c9SBarry Smith   Mat_MPIAIJ     *a,*oldmat = (Mat_MPIAIJ*)matin->data;
3280dfbe8321SBarry Smith   PetscErrorCode ierr;
3281d6dfbf8fSBarry Smith 
32823a40ed3dSBarry Smith   PetscFunctionBegin;
3283416022c9SBarry Smith   *newmat       = 0;
32847adad957SLisandro Dalcin   ierr = MatCreate(((PetscObject)matin)->comm,&mat);CHKERRQ(ierr);
3285d0f46423SBarry Smith   ierr = MatSetSizes(mat,matin->rmap->n,matin->cmap->n,matin->rmap->N,matin->cmap->N);CHKERRQ(ierr);
3286a2f3521dSMark F. Adams   ierr = MatSetBlockSizes(mat,matin->rmap->bs,matin->cmap->bs);CHKERRQ(ierr);
32877adad957SLisandro Dalcin   ierr = MatSetType(mat,((PetscObject)matin)->type_name);CHKERRQ(ierr);
32881d5dac46SHong Zhang   ierr = PetscMemcpy(mat->ops,matin->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3289273d9f13SBarry Smith   a    = (Mat_MPIAIJ*)mat->data;
3290e1b6402fSHong Zhang 
3291d5f3da31SBarry Smith   mat->factortype    = matin->factortype;
3292d0f46423SBarry Smith   mat->rmap->bs      = matin->rmap->bs;
3293a2f3521dSMark F. Adams   mat->cmap->bs      = matin->cmap->bs;
3294c456f294SBarry Smith   mat->assembled    = PETSC_TRUE;
3295e7641de0SSatish Balay   mat->insertmode   = NOT_SET_VALUES;
3296273d9f13SBarry Smith   mat->preallocated = PETSC_TRUE;
3297d6dfbf8fSBarry Smith 
329817699dbbSLois Curfman McInnes   a->size           = oldmat->size;
329917699dbbSLois Curfman McInnes   a->rank           = oldmat->rank;
3300e7641de0SSatish Balay   a->donotstash     = oldmat->donotstash;
3301e7641de0SSatish Balay   a->roworiented    = oldmat->roworiented;
3302e7641de0SSatish Balay   a->rowindices     = 0;
3303bcd2baecSBarry Smith   a->rowvalues      = 0;
3304bcd2baecSBarry Smith   a->getrowactive   = PETSC_FALSE;
3305d6dfbf8fSBarry Smith 
33061e1e43feSBarry Smith   ierr = PetscLayoutReference(matin->rmap,&mat->rmap);CHKERRQ(ierr);
33071e1e43feSBarry Smith   ierr = PetscLayoutReference(matin->cmap,&mat->cmap);CHKERRQ(ierr);
3308899cda47SBarry Smith 
33092ee70a88SLois Curfman McInnes   if (oldmat->colmap) {
3310aa482453SBarry Smith #if defined (PETSC_USE_CTABLE)
33110f5bd95cSBarry Smith     ierr = PetscTableCreateCopy(oldmat->colmap,&a->colmap);CHKERRQ(ierr);
3312b1fc9764SSatish Balay #else
3313d0f46423SBarry Smith     ierr = PetscMalloc((mat->cmap->N)*sizeof(PetscInt),&a->colmap);CHKERRQ(ierr);
3314d0f46423SBarry Smith     ierr = PetscLogObjectMemory(mat,(mat->cmap->N)*sizeof(PetscInt));CHKERRQ(ierr);
3315d0f46423SBarry Smith     ierr = PetscMemcpy(a->colmap,oldmat->colmap,(mat->cmap->N)*sizeof(PetscInt));CHKERRQ(ierr);
3316b1fc9764SSatish Balay #endif
3317416022c9SBarry Smith   } else a->colmap = 0;
33183f41c07dSBarry Smith   if (oldmat->garray) {
3319b1d57f15SBarry Smith     PetscInt len;
3320d0f46423SBarry Smith     len  = oldmat->B->cmap->n;
3321b1d57f15SBarry Smith     ierr = PetscMalloc((len+1)*sizeof(PetscInt),&a->garray);CHKERRQ(ierr);
332252e6d16bSBarry Smith     ierr = PetscLogObjectMemory(mat,len*sizeof(PetscInt));CHKERRQ(ierr);
3323b1d57f15SBarry Smith     if (len) { ierr = PetscMemcpy(a->garray,oldmat->garray,len*sizeof(PetscInt));CHKERRQ(ierr); }
3324416022c9SBarry Smith   } else a->garray = 0;
3325d6dfbf8fSBarry Smith 
3326416022c9SBarry Smith   ierr = VecDuplicate(oldmat->lvec,&a->lvec);CHKERRQ(ierr);
332752e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,a->lvec);CHKERRQ(ierr);
3328a56f8943SBarry Smith   ierr = VecScatterCopy(oldmat->Mvctx,&a->Mvctx);CHKERRQ(ierr);
332952e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,a->Mvctx);CHKERRQ(ierr);
33302e8a6d31SBarry Smith   ierr = MatDuplicate(oldmat->A,cpvalues,&a->A);CHKERRQ(ierr);
333152e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,a->A);CHKERRQ(ierr);
33322e8a6d31SBarry Smith   ierr = MatDuplicate(oldmat->B,cpvalues,&a->B);CHKERRQ(ierr);
333352e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,a->B);CHKERRQ(ierr);
33347adad957SLisandro Dalcin   ierr = PetscFListDuplicate(((PetscObject)matin)->qlist,&((PetscObject)mat)->qlist);CHKERRQ(ierr);
33358a729477SBarry Smith   *newmat = mat;
33363a40ed3dSBarry Smith   PetscFunctionReturn(0);
33378a729477SBarry Smith }
3338416022c9SBarry Smith 
33391a4ee126SBarry Smith 
33401a4ee126SBarry Smith 
33414a2ae208SSatish Balay #undef __FUNCT__
33425bba2384SShri Abhyankar #define __FUNCT__ "MatLoad_MPIAIJ"
3343112444f4SShri Abhyankar PetscErrorCode MatLoad_MPIAIJ(Mat newMat, PetscViewer viewer)
33448fb81238SShri Abhyankar {
33458fb81238SShri Abhyankar   PetscScalar    *vals,*svals;
33468fb81238SShri Abhyankar   MPI_Comm       comm = ((PetscObject)viewer)->comm;
33478fb81238SShri Abhyankar   PetscErrorCode ierr;
33481a4ee126SBarry Smith   PetscMPIInt    rank,size,tag = ((PetscObject)viewer)->tag;
33498fb81238SShri Abhyankar   PetscInt       i,nz,j,rstart,rend,mmax,maxnz = 0,grows,gcols;
33508fb81238SShri Abhyankar   PetscInt       header[4],*rowlengths = 0,M,N,m,*cols;
33518fb81238SShri Abhyankar   PetscInt       *ourlens = PETSC_NULL,*procsnz = PETSC_NULL,*offlens = PETSC_NULL,jj,*mycols,*smycols;
33528fb81238SShri Abhyankar   PetscInt       cend,cstart,n,*rowners,sizesset=1;
33538fb81238SShri Abhyankar   int            fd;
335408ea439dSMark F. Adams   PetscInt       bs = 1;
33558fb81238SShri Abhyankar 
33568fb81238SShri Abhyankar   PetscFunctionBegin;
33578fb81238SShri Abhyankar   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
33588fb81238SShri Abhyankar   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
33598fb81238SShri Abhyankar   if (!rank) {
33608fb81238SShri Abhyankar     ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
33618fb81238SShri Abhyankar     ierr = PetscBinaryRead(fd,(char *)header,4,PETSC_INT);CHKERRQ(ierr);
33628fb81238SShri Abhyankar     if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object");
33638fb81238SShri Abhyankar   }
33648fb81238SShri Abhyankar 
336508ea439dSMark F. Adams   ierr = PetscOptionsBegin(comm,PETSC_NULL,"Options for loading SEQAIJ matrix","Mat");CHKERRQ(ierr);
336608ea439dSMark F. Adams   ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);CHKERRQ(ierr);
336708ea439dSMark F. Adams   ierr = PetscOptionsEnd();CHKERRQ(ierr);
336808ea439dSMark F. Adams 
33698fb81238SShri Abhyankar   if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) sizesset = 0;
33708fb81238SShri Abhyankar 
33718fb81238SShri Abhyankar   ierr = MPI_Bcast(header+1,3,MPIU_INT,0,comm);CHKERRQ(ierr);
33728fb81238SShri Abhyankar   M = header[1]; N = header[2];
33738fb81238SShri Abhyankar   /* If global rows/cols are set to PETSC_DECIDE, set it to the sizes given in the file */
33748fb81238SShri Abhyankar   if (sizesset && newMat->rmap->N < 0) newMat->rmap->N = M;
33758fb81238SShri Abhyankar   if (sizesset && newMat->cmap->N < 0) newMat->cmap->N = N;
33768fb81238SShri Abhyankar 
33778fb81238SShri Abhyankar   /* If global sizes are set, check if they are consistent with that given in the file */
33788fb81238SShri Abhyankar   if (sizesset) {
33798fb81238SShri Abhyankar     ierr = MatGetSize(newMat,&grows,&gcols);CHKERRQ(ierr);
33808fb81238SShri Abhyankar   }
3381abd38a8fSBarry Smith   if (sizesset && newMat->rmap->N != grows) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Inconsistent # of rows:Matrix in file has (%d) and input matrix has (%d)",M,grows);
3382abd38a8fSBarry Smith   if (sizesset && newMat->cmap->N != gcols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Inconsistent # of cols:Matrix in file has (%d) and input matrix has (%d)",N,gcols);
33838fb81238SShri Abhyankar 
338408ea439dSMark F. Adams   /* determine ownership of all (block) rows */
338508ea439dSMark F. Adams   if( M%bs ) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Inconsistent # of rows (%d) and block size (%d)",M,bs);
338608ea439dSMark F. Adams   if (newMat->rmap->n < 0 ) m    = bs*((M/bs)/size + (((M/bs) % size) > rank)); /* PETSC_DECIDE */
33874683f7a4SShri Abhyankar   else m = newMat->rmap->n; /* Set by user */
33888fb81238SShri Abhyankar 
33898fb81238SShri Abhyankar   ierr = PetscMalloc((size+1)*sizeof(PetscInt),&rowners);CHKERRQ(ierr);
33908fb81238SShri Abhyankar   ierr = MPI_Allgather(&m,1,MPIU_INT,rowners+1,1,MPIU_INT,comm);CHKERRQ(ierr);
33918fb81238SShri Abhyankar 
33928fb81238SShri Abhyankar   /* First process needs enough room for process with most rows */
33938fb81238SShri Abhyankar   if (!rank) {
33948fb81238SShri Abhyankar     mmax       = rowners[1];
33958fb81238SShri Abhyankar     for (i=2; i<size; i++) {
33968fb81238SShri Abhyankar       mmax = PetscMax(mmax,rowners[i]);
33978fb81238SShri Abhyankar     }
33988fb81238SShri Abhyankar   } else mmax = m;
33998fb81238SShri Abhyankar 
34008fb81238SShri Abhyankar   rowners[0] = 0;
34018fb81238SShri Abhyankar   for (i=2; i<=size; i++) {
34028fb81238SShri Abhyankar     rowners[i] += rowners[i-1];
34038fb81238SShri Abhyankar   }
34048fb81238SShri Abhyankar   rstart = rowners[rank];
34058fb81238SShri Abhyankar   rend   = rowners[rank+1];
34068fb81238SShri Abhyankar 
34078fb81238SShri Abhyankar   /* distribute row lengths to all processors */
34088fb81238SShri Abhyankar   ierr    = PetscMalloc2(mmax,PetscInt,&ourlens,mmax,PetscInt,&offlens);CHKERRQ(ierr);
34098fb81238SShri Abhyankar   if (!rank) {
34108fb81238SShri Abhyankar     ierr = PetscBinaryRead(fd,ourlens,m,PETSC_INT);CHKERRQ(ierr);
34118fb81238SShri Abhyankar     ierr = PetscMalloc(m*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
34128fb81238SShri Abhyankar     ierr = PetscMalloc(size*sizeof(PetscInt),&procsnz);CHKERRQ(ierr);
34138fb81238SShri Abhyankar     ierr = PetscMemzero(procsnz,size*sizeof(PetscInt));CHKERRQ(ierr);
34148fb81238SShri Abhyankar     for (j=0; j<m; j++) {
34158fb81238SShri Abhyankar       procsnz[0] += ourlens[j];
34168fb81238SShri Abhyankar     }
34178fb81238SShri Abhyankar     for (i=1; i<size; i++) {
34188fb81238SShri Abhyankar       ierr = PetscBinaryRead(fd,rowlengths,rowners[i+1]-rowners[i],PETSC_INT);CHKERRQ(ierr);
34198fb81238SShri Abhyankar       /* calculate the number of nonzeros on each processor */
34208fb81238SShri Abhyankar       for (j=0; j<rowners[i+1]-rowners[i]; j++) {
34218fb81238SShri Abhyankar         procsnz[i] += rowlengths[j];
34228fb81238SShri Abhyankar       }
3423a25532f0SBarry Smith       ierr = MPIULong_Send(rowlengths,rowners[i+1]-rowners[i],MPIU_INT,i,tag,comm);CHKERRQ(ierr);
34248fb81238SShri Abhyankar     }
34258fb81238SShri Abhyankar     ierr = PetscFree(rowlengths);CHKERRQ(ierr);
34268fb81238SShri Abhyankar   } else {
3427a25532f0SBarry Smith     ierr = MPIULong_Recv(ourlens,m,MPIU_INT,0,tag,comm);CHKERRQ(ierr);
34288fb81238SShri Abhyankar   }
34298fb81238SShri Abhyankar 
34308fb81238SShri Abhyankar   if (!rank) {
34318fb81238SShri Abhyankar     /* determine max buffer needed and allocate it */
34328fb81238SShri Abhyankar     maxnz = 0;
34338fb81238SShri Abhyankar     for (i=0; i<size; i++) {
34348fb81238SShri Abhyankar       maxnz = PetscMax(maxnz,procsnz[i]);
34358fb81238SShri Abhyankar     }
34368fb81238SShri Abhyankar     ierr = PetscMalloc(maxnz*sizeof(PetscInt),&cols);CHKERRQ(ierr);
34378fb81238SShri Abhyankar 
34388fb81238SShri Abhyankar     /* read in my part of the matrix column indices  */
34398fb81238SShri Abhyankar     nz   = procsnz[0];
34408fb81238SShri Abhyankar     ierr = PetscMalloc(nz*sizeof(PetscInt),&mycols);CHKERRQ(ierr);
34418fb81238SShri Abhyankar     ierr = PetscBinaryRead(fd,mycols,nz,PETSC_INT);CHKERRQ(ierr);
34428fb81238SShri Abhyankar 
34438fb81238SShri Abhyankar     /* read in every one elses and ship off */
34448fb81238SShri Abhyankar     for (i=1; i<size; i++) {
34458fb81238SShri Abhyankar       nz     = procsnz[i];
34468fb81238SShri Abhyankar       ierr   = PetscBinaryRead(fd,cols,nz,PETSC_INT);CHKERRQ(ierr);
3447a25532f0SBarry Smith       ierr   = MPIULong_Send(cols,nz,MPIU_INT,i,tag,comm);CHKERRQ(ierr);
34488fb81238SShri Abhyankar     }
34498fb81238SShri Abhyankar     ierr = PetscFree(cols);CHKERRQ(ierr);
34508fb81238SShri Abhyankar   } else {
34518fb81238SShri Abhyankar     /* determine buffer space needed for message */
34528fb81238SShri Abhyankar     nz = 0;
34538fb81238SShri Abhyankar     for (i=0; i<m; i++) {
34548fb81238SShri Abhyankar       nz += ourlens[i];
34558fb81238SShri Abhyankar     }
34568fb81238SShri Abhyankar     ierr = PetscMalloc(nz*sizeof(PetscInt),&mycols);CHKERRQ(ierr);
34578fb81238SShri Abhyankar 
34588fb81238SShri Abhyankar     /* receive message of column indices*/
3459a25532f0SBarry Smith     ierr = MPIULong_Recv(mycols,nz,MPIU_INT,0,tag,comm);CHKERRQ(ierr);
34608fb81238SShri Abhyankar   }
34618fb81238SShri Abhyankar 
34628fb81238SShri Abhyankar   /* determine column ownership if matrix is not square */
34638fb81238SShri Abhyankar   if (N != M) {
34648fb81238SShri Abhyankar     if (newMat->cmap->n < 0) n      = N/size + ((N % size) > rank);
34658fb81238SShri Abhyankar     else n = newMat->cmap->n;
34668fb81238SShri Abhyankar     ierr   = MPI_Scan(&n,&cend,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
34678fb81238SShri Abhyankar     cstart = cend - n;
34688fb81238SShri Abhyankar   } else {
34698fb81238SShri Abhyankar     cstart = rstart;
34708fb81238SShri Abhyankar     cend   = rend;
34718fb81238SShri Abhyankar     n      = cend - cstart;
34728fb81238SShri Abhyankar   }
34738fb81238SShri Abhyankar 
34748fb81238SShri Abhyankar   /* loop over local rows, determining number of off diagonal entries */
34758fb81238SShri Abhyankar   ierr = PetscMemzero(offlens,m*sizeof(PetscInt));CHKERRQ(ierr);
34768fb81238SShri Abhyankar   jj = 0;
34778fb81238SShri Abhyankar   for (i=0; i<m; i++) {
34788fb81238SShri Abhyankar     for (j=0; j<ourlens[i]; j++) {
34798fb81238SShri Abhyankar       if (mycols[jj] < cstart || mycols[jj] >= cend) offlens[i]++;
34808fb81238SShri Abhyankar       jj++;
34818fb81238SShri Abhyankar     }
34828fb81238SShri Abhyankar   }
34838fb81238SShri Abhyankar 
34848fb81238SShri Abhyankar   for (i=0; i<m; i++) {
34858fb81238SShri Abhyankar     ourlens[i] -= offlens[i];
34868fb81238SShri Abhyankar   }
34878fb81238SShri Abhyankar   if (!sizesset) {
34888fb81238SShri Abhyankar     ierr = MatSetSizes(newMat,m,n,M,N);CHKERRQ(ierr);
34898fb81238SShri Abhyankar   }
349008ea439dSMark F. Adams 
349108ea439dSMark F. Adams   if (bs > 1) {ierr = MatSetBlockSize(newMat,bs);CHKERRQ(ierr);}
349208ea439dSMark F. Adams 
34938fb81238SShri Abhyankar   ierr = MatMPIAIJSetPreallocation(newMat,0,ourlens,0,offlens);CHKERRQ(ierr);
34948fb81238SShri Abhyankar 
34958fb81238SShri Abhyankar   for (i=0; i<m; i++) {
34968fb81238SShri Abhyankar     ourlens[i] += offlens[i];
34978fb81238SShri Abhyankar   }
34988fb81238SShri Abhyankar 
34998fb81238SShri Abhyankar   if (!rank) {
35008fb81238SShri Abhyankar     ierr = PetscMalloc((maxnz+1)*sizeof(PetscScalar),&vals);CHKERRQ(ierr);
35018fb81238SShri Abhyankar 
35028fb81238SShri Abhyankar     /* read in my part of the matrix numerical values  */
35038fb81238SShri Abhyankar     nz   = procsnz[0];
35048fb81238SShri Abhyankar     ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr);
35058fb81238SShri Abhyankar 
35068fb81238SShri Abhyankar     /* insert into matrix */
35078fb81238SShri Abhyankar     jj      = rstart;
35088fb81238SShri Abhyankar     smycols = mycols;
35098fb81238SShri Abhyankar     svals   = vals;
35108fb81238SShri Abhyankar     for (i=0; i<m; i++) {
35118fb81238SShri Abhyankar       ierr = MatSetValues_MPIAIJ(newMat,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
35128fb81238SShri Abhyankar       smycols += ourlens[i];
35138fb81238SShri Abhyankar       svals   += ourlens[i];
35148fb81238SShri Abhyankar       jj++;
35158fb81238SShri Abhyankar     }
35168fb81238SShri Abhyankar 
35178fb81238SShri Abhyankar     /* read in other processors and ship out */
35188fb81238SShri Abhyankar     for (i=1; i<size; i++) {
35198fb81238SShri Abhyankar       nz     = procsnz[i];
35208fb81238SShri Abhyankar       ierr   = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr);
3521a25532f0SBarry Smith       ierr   = MPIULong_Send(vals,nz,MPIU_SCALAR,i,((PetscObject)newMat)->tag,comm);CHKERRQ(ierr);
35228fb81238SShri Abhyankar     }
35238fb81238SShri Abhyankar     ierr = PetscFree(procsnz);CHKERRQ(ierr);
35248fb81238SShri Abhyankar   } else {
35258fb81238SShri Abhyankar     /* receive numeric values */
35268fb81238SShri Abhyankar     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&vals);CHKERRQ(ierr);
35278fb81238SShri Abhyankar 
35288fb81238SShri Abhyankar     /* receive message of values*/
3529a25532f0SBarry Smith     ierr   = MPIULong_Recv(vals,nz,MPIU_SCALAR,0,((PetscObject)newMat)->tag,comm);CHKERRQ(ierr);
35308fb81238SShri Abhyankar 
35318fb81238SShri Abhyankar     /* insert into matrix */
35328fb81238SShri Abhyankar     jj      = rstart;
35338fb81238SShri Abhyankar     smycols = mycols;
35348fb81238SShri Abhyankar     svals   = vals;
35358fb81238SShri Abhyankar     for (i=0; i<m; i++) {
35368fb81238SShri Abhyankar       ierr     = MatSetValues_MPIAIJ(newMat,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
35378fb81238SShri Abhyankar       smycols += ourlens[i];
35388fb81238SShri Abhyankar       svals   += ourlens[i];
35398fb81238SShri Abhyankar       jj++;
35408fb81238SShri Abhyankar     }
35418fb81238SShri Abhyankar   }
35428fb81238SShri Abhyankar   ierr = PetscFree2(ourlens,offlens);CHKERRQ(ierr);
35438fb81238SShri Abhyankar   ierr = PetscFree(vals);CHKERRQ(ierr);
35448fb81238SShri Abhyankar   ierr = PetscFree(mycols);CHKERRQ(ierr);
35458fb81238SShri Abhyankar   ierr = PetscFree(rowners);CHKERRQ(ierr);
35468fb81238SShri Abhyankar   ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
35478fb81238SShri Abhyankar   ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
354808ea439dSMark F. Adams 
35498fb81238SShri Abhyankar   PetscFunctionReturn(0);
35508fb81238SShri Abhyankar }
35518fb81238SShri Abhyankar 
35528fb81238SShri Abhyankar #undef __FUNCT__
35534a2ae208SSatish Balay #define __FUNCT__ "MatGetSubMatrix_MPIAIJ"
35544aa3045dSJed Brown PetscErrorCode MatGetSubMatrix_MPIAIJ(Mat mat,IS isrow,IS iscol,MatReuse call,Mat *newmat)
35554aa3045dSJed Brown {
35564aa3045dSJed Brown   PetscErrorCode ierr;
35574aa3045dSJed Brown   IS             iscol_local;
35584aa3045dSJed Brown   PetscInt       csize;
35594aa3045dSJed Brown 
35604aa3045dSJed Brown   PetscFunctionBegin;
35614aa3045dSJed Brown   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
3562b79d0421SJed Brown   if (call == MAT_REUSE_MATRIX) {
3563b79d0421SJed Brown     ierr = PetscObjectQuery((PetscObject)*newmat,"ISAllGather",(PetscObject*)&iscol_local);CHKERRQ(ierr);
3564e32f2f54SBarry Smith     if (!iscol_local) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Submatrix passed in was not used before, cannot reuse");
3565b79d0421SJed Brown   } else {
3566c5bfad50SMark F. Adams     PetscInt cbs;
3567c5bfad50SMark F. Adams     ierr = ISGetBlockSize(iscol,&cbs); CHKERRQ(ierr);
35684aa3045dSJed Brown     ierr = ISAllGather(iscol,&iscol_local);CHKERRQ(ierr);
3569c5bfad50SMark F. Adams     ierr = ISSetBlockSize(iscol_local,cbs); CHKERRQ(ierr);
3570b79d0421SJed Brown   }
35714aa3045dSJed Brown   ierr = MatGetSubMatrix_MPIAIJ_Private(mat,isrow,iscol_local,csize,call,newmat);CHKERRQ(ierr);
3572b79d0421SJed Brown   if (call == MAT_INITIAL_MATRIX) {
3573b79d0421SJed Brown     ierr = PetscObjectCompose((PetscObject)*newmat,"ISAllGather",(PetscObject)iscol_local);CHKERRQ(ierr);
35746bf464f9SBarry Smith     ierr = ISDestroy(&iscol_local);CHKERRQ(ierr);
3575b79d0421SJed Brown   }
35764aa3045dSJed Brown   PetscFunctionReturn(0);
35774aa3045dSJed Brown }
35784aa3045dSJed Brown 
357929dcf524SDmitry Karpeev extern PetscErrorCode MatGetSubMatrices_MPIAIJ_Local(Mat,PetscInt,const IS[],const IS[],MatReuse,PetscBool*,Mat*);
35804aa3045dSJed Brown #undef __FUNCT__
35814aa3045dSJed Brown #define __FUNCT__ "MatGetSubMatrix_MPIAIJ_Private"
3582a0ff6018SBarry Smith /*
358329da9460SBarry Smith     Not great since it makes two copies of the submatrix, first an SeqAIJ
358429da9460SBarry Smith   in local and then by concatenating the local matrices the end result.
358529da9460SBarry Smith   Writing it directly would be much like MatGetSubMatrices_MPIAIJ()
35864aa3045dSJed Brown 
35874aa3045dSJed Brown   Note: This requires a sequential iscol with all indices.
3588a0ff6018SBarry Smith */
35894aa3045dSJed Brown PetscErrorCode MatGetSubMatrix_MPIAIJ_Private(Mat mat,IS isrow,IS iscol,PetscInt csize,MatReuse call,Mat *newmat)
3590a0ff6018SBarry Smith {
3591dfbe8321SBarry Smith   PetscErrorCode ierr;
359232dcc486SBarry Smith   PetscMPIInt    rank,size;
3593a2f3521dSMark F. Adams   PetscInt       i,m,n,rstart,row,rend,nz,*cwork,j,bs,cbs;
359429dcf524SDmitry Karpeev   PetscInt       *ii,*jj,nlocal,*dlens,*olens,dlen,olen,jend,mglobal,ncol;
359529dcf524SDmitry Karpeev   PetscBool      allcolumns, colflag;
359629dcf524SDmitry Karpeev   Mat            M,Mreuse;
3597a77337e4SBarry Smith   MatScalar      *vwork,*aa;
35987adad957SLisandro Dalcin   MPI_Comm       comm = ((PetscObject)mat)->comm;
359900e6dbe6SBarry Smith   Mat_SeqAIJ     *aij;
36007e2c5f70SBarry Smith 
3601a0ff6018SBarry Smith 
3602a0ff6018SBarry Smith   PetscFunctionBegin;
36031dab6e02SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
36041dab6e02SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
360500e6dbe6SBarry Smith 
360629dcf524SDmitry Karpeev   ierr = ISIdentity(iscol,&colflag);CHKERRQ(ierr);
360729dcf524SDmitry Karpeev   ierr = ISGetLocalSize(iscol,&ncol);CHKERRQ(ierr);
360829dcf524SDmitry Karpeev   if (colflag && ncol == mat->cmap->N){
360929dcf524SDmitry Karpeev     allcolumns = PETSC_TRUE;
361029dcf524SDmitry Karpeev   } else {
361129dcf524SDmitry Karpeev     allcolumns = PETSC_FALSE;
361229dcf524SDmitry Karpeev   }
3613fee21e36SBarry Smith   if (call ==  MAT_REUSE_MATRIX) {
3614fee21e36SBarry Smith     ierr = PetscObjectQuery((PetscObject)*newmat,"SubMatrix",(PetscObject *)&Mreuse);CHKERRQ(ierr);
3615e32f2f54SBarry Smith     if (!Mreuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Submatrix passed in was not used before, cannot reuse");
361629dcf524SDmitry Karpeev     ierr  = MatGetSubMatrices_MPIAIJ_Local(mat,1,&isrow,&iscol,MAT_REUSE_MATRIX,&allcolumns,&Mreuse);CHKERRQ(ierr);
3617fee21e36SBarry Smith   } else {
361829dcf524SDmitry Karpeev     ierr   = MatGetSubMatrices_MPIAIJ_Local(mat,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&allcolumns,&Mreuse);CHKERRQ(ierr);
3619fee21e36SBarry Smith   }
3620a0ff6018SBarry Smith 
3621a0ff6018SBarry Smith   /*
3622a0ff6018SBarry Smith       m - number of local rows
3623a0ff6018SBarry Smith       n - number of columns (same on all processors)
3624a0ff6018SBarry Smith       rstart - first row in new global matrix generated
3625a0ff6018SBarry Smith   */
3626fee21e36SBarry Smith   ierr = MatGetSize(Mreuse,&m,&n);CHKERRQ(ierr);
3627a2f3521dSMark F. Adams   ierr = MatGetBlockSizes(Mreuse,&bs,&cbs);CHKERRQ(ierr);
3628a0ff6018SBarry Smith   if (call == MAT_INITIAL_MATRIX) {
3629fee21e36SBarry Smith     aij = (Mat_SeqAIJ*)(Mreuse)->data;
363000e6dbe6SBarry Smith     ii  = aij->i;
363100e6dbe6SBarry Smith     jj  = aij->j;
363200e6dbe6SBarry Smith 
3633a0ff6018SBarry Smith     /*
363400e6dbe6SBarry Smith         Determine the number of non-zeros in the diagonal and off-diagonal
363500e6dbe6SBarry Smith         portions of the matrix in order to do correct preallocation
3636a0ff6018SBarry Smith     */
363700e6dbe6SBarry Smith 
363800e6dbe6SBarry Smith     /* first get start and end of "diagonal" columns */
36396a6a5d1dSBarry Smith     if (csize == PETSC_DECIDE) {
3640ab50ec6bSBarry Smith       ierr = ISGetSize(isrow,&mglobal);CHKERRQ(ierr);
3641ab50ec6bSBarry Smith       if (mglobal == n) { /* square matrix */
3642e2c4fddaSBarry Smith 	nlocal = m;
36436a6a5d1dSBarry Smith       } else {
3644ab50ec6bSBarry Smith         nlocal = n/size + ((n % size) > rank);
3645ab50ec6bSBarry Smith       }
3646ab50ec6bSBarry Smith     } else {
36476a6a5d1dSBarry Smith       nlocal = csize;
36486a6a5d1dSBarry Smith     }
3649b1d57f15SBarry Smith     ierr   = MPI_Scan(&nlocal,&rend,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
365000e6dbe6SBarry Smith     rstart = rend - nlocal;
365165e19b50SBarry Smith     if (rank == size - 1 && rend != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local column sizes %D do not add up to total number of columns %D",rend,n);
365200e6dbe6SBarry Smith 
365300e6dbe6SBarry Smith     /* next, compute all the lengths */
3654b1d57f15SBarry Smith     ierr  = PetscMalloc((2*m+1)*sizeof(PetscInt),&dlens);CHKERRQ(ierr);
365500e6dbe6SBarry Smith     olens = dlens + m;
365600e6dbe6SBarry Smith     for (i=0; i<m; i++) {
365700e6dbe6SBarry Smith       jend = ii[i+1] - ii[i];
365800e6dbe6SBarry Smith       olen = 0;
365900e6dbe6SBarry Smith       dlen = 0;
366000e6dbe6SBarry Smith       for (j=0; j<jend; j++) {
366100e6dbe6SBarry Smith         if (*jj < rstart || *jj >= rend) olen++;
366200e6dbe6SBarry Smith         else dlen++;
366300e6dbe6SBarry Smith         jj++;
366400e6dbe6SBarry Smith       }
366500e6dbe6SBarry Smith       olens[i] = olen;
366600e6dbe6SBarry Smith       dlens[i] = dlen;
366700e6dbe6SBarry Smith     }
3668f69a0ea3SMatthew Knepley     ierr = MatCreate(comm,&M);CHKERRQ(ierr);
3669f69a0ea3SMatthew Knepley     ierr = MatSetSizes(M,m,nlocal,PETSC_DECIDE,n);CHKERRQ(ierr);
3670a2f3521dSMark F. Adams     ierr = MatSetBlockSizes(M,bs,cbs); CHKERRQ(ierr);
36717adad957SLisandro Dalcin     ierr = MatSetType(M,((PetscObject)mat)->type_name);CHKERRQ(ierr);
3672e2d9671bSKris Buschelman     ierr = MatMPIAIJSetPreallocation(M,0,dlens,0,olens);CHKERRQ(ierr);
3673606d414cSSatish Balay     ierr = PetscFree(dlens);CHKERRQ(ierr);
3674a0ff6018SBarry Smith   } else {
3675b1d57f15SBarry Smith     PetscInt ml,nl;
3676a0ff6018SBarry Smith 
3677a0ff6018SBarry Smith     M = *newmat;
3678a0ff6018SBarry Smith     ierr = MatGetLocalSize(M,&ml,&nl);CHKERRQ(ierr);
3679e32f2f54SBarry Smith     if (ml != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Previous matrix must be same size/layout as request");
3680a0ff6018SBarry Smith     ierr = MatZeroEntries(M);CHKERRQ(ierr);
3681c48de900SBarry Smith     /*
3682c48de900SBarry Smith          The next two lines are needed so we may call MatSetValues_MPIAIJ() below directly,
3683c48de900SBarry Smith        rather than the slower MatSetValues().
3684c48de900SBarry Smith     */
3685c48de900SBarry Smith     M->was_assembled = PETSC_TRUE;
3686c48de900SBarry Smith     M->assembled     = PETSC_FALSE;
3687a0ff6018SBarry Smith   }
3688a0ff6018SBarry Smith   ierr = MatGetOwnershipRange(M,&rstart,&rend);CHKERRQ(ierr);
3689fee21e36SBarry Smith   aij = (Mat_SeqAIJ*)(Mreuse)->data;
369000e6dbe6SBarry Smith   ii  = aij->i;
369100e6dbe6SBarry Smith   jj  = aij->j;
369200e6dbe6SBarry Smith   aa  = aij->a;
3693a0ff6018SBarry Smith   for (i=0; i<m; i++) {
3694a0ff6018SBarry Smith     row   = rstart + i;
369500e6dbe6SBarry Smith     nz    = ii[i+1] - ii[i];
369600e6dbe6SBarry Smith     cwork = jj;     jj += nz;
369700e6dbe6SBarry Smith     vwork = aa;     aa += nz;
36988c638d02SBarry Smith     ierr = MatSetValues_MPIAIJ(M,1,&row,nz,cwork,vwork,INSERT_VALUES);CHKERRQ(ierr);
3699a0ff6018SBarry Smith   }
3700a0ff6018SBarry Smith 
3701a0ff6018SBarry Smith   ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3702a0ff6018SBarry Smith   ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3703a0ff6018SBarry Smith   *newmat = M;
3704fee21e36SBarry Smith 
3705fee21e36SBarry Smith   /* save submatrix used in processor for next request */
3706fee21e36SBarry Smith   if (call ==  MAT_INITIAL_MATRIX) {
3707fee21e36SBarry Smith     ierr = PetscObjectCompose((PetscObject)M,"SubMatrix",(PetscObject)Mreuse);CHKERRQ(ierr);
3708bf0cc555SLisandro Dalcin     ierr = MatDestroy(&Mreuse);CHKERRQ(ierr);
3709fee21e36SBarry Smith   }
3710fee21e36SBarry Smith 
3711a0ff6018SBarry Smith   PetscFunctionReturn(0);
3712a0ff6018SBarry Smith }
3713273d9f13SBarry Smith 
3714e2e86b8fSSatish Balay EXTERN_C_BEGIN
37154a2ae208SSatish Balay #undef __FUNCT__
3716ccd8e176SBarry Smith #define __FUNCT__ "MatMPIAIJSetPreallocationCSR_MPIAIJ"
37177087cfbeSBarry Smith PetscErrorCode  MatMPIAIJSetPreallocationCSR_MPIAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
3718ccd8e176SBarry Smith {
3719899cda47SBarry Smith   PetscInt       m,cstart, cend,j,nnz,i,d;
3720899cda47SBarry Smith   PetscInt       *d_nnz,*o_nnz,nnz_max = 0,rstart,ii;
3721ccd8e176SBarry Smith   const PetscInt *JJ;
3722ccd8e176SBarry Smith   PetscScalar    *values;
3723ccd8e176SBarry Smith   PetscErrorCode ierr;
3724ccd8e176SBarry Smith 
3725ccd8e176SBarry Smith   PetscFunctionBegin;
3726e32f2f54SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Ii[0] must be 0 it is %D",Ii[0]);
3727899cda47SBarry Smith 
372826283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
372926283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
3730d0f46423SBarry Smith   m      = B->rmap->n;
3731d0f46423SBarry Smith   cstart = B->cmap->rstart;
3732d0f46423SBarry Smith   cend   = B->cmap->rend;
3733d0f46423SBarry Smith   rstart = B->rmap->rstart;
3734899cda47SBarry Smith 
37351d79065fSBarry Smith   ierr  = PetscMalloc2(m,PetscInt,&d_nnz,m,PetscInt,&o_nnz);CHKERRQ(ierr);
3736ccd8e176SBarry Smith 
3737ecc77c7aSBarry Smith #if defined(PETSC_USE_DEBUGGING)
3738ecc77c7aSBarry Smith   for (i=0; i<m; i++) {
3739ecc77c7aSBarry Smith     nnz     = Ii[i+1]- Ii[i];
3740ecc77c7aSBarry Smith     JJ      = J + Ii[i];
3741e32f2f54SBarry Smith     if (nnz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local row %D has a negative %D number of columns",i,nnz);
3742ecc77c7aSBarry Smith     if (nnz && (JJ[0] < 0)) SETERRRQ1(PETSC_ERR_ARG_WRONGSTATE,"Row %D starts with negative column index",i,j);
3743d0f46423SBarry Smith     if (nnz && (JJ[nnz-1] >= B->cmap->N) SETERRRQ3(PETSC_ERR_ARG_WRONGSTATE,"Row %D ends with too large a column index %D (max allowed %D)",i,JJ[nnz-1],B->cmap->N);
3744ecc77c7aSBarry Smith   }
3745ecc77c7aSBarry Smith #endif
3746ecc77c7aSBarry Smith 
3747ccd8e176SBarry Smith   for (i=0; i<m; i++) {
3748b7940d39SSatish Balay     nnz     = Ii[i+1]- Ii[i];
3749b7940d39SSatish Balay     JJ      = J + Ii[i];
3750ccd8e176SBarry Smith     nnz_max = PetscMax(nnz_max,nnz);
3751ccd8e176SBarry Smith     d       = 0;
37520daa03b5SJed Brown     for (j=0; j<nnz; j++) {
37530daa03b5SJed Brown       if (cstart <= JJ[j] && JJ[j] < cend) d++;
3754ccd8e176SBarry Smith     }
3755ccd8e176SBarry Smith     d_nnz[i] = d;
3756ccd8e176SBarry Smith     o_nnz[i] = nnz - d;
3757ccd8e176SBarry Smith   }
3758ccd8e176SBarry Smith   ierr = MatMPIAIJSetPreallocation(B,0,d_nnz,0,o_nnz);CHKERRQ(ierr);
37591d79065fSBarry Smith   ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr);
3760ccd8e176SBarry Smith 
3761ccd8e176SBarry Smith   if (v) values = (PetscScalar*)v;
3762ccd8e176SBarry Smith   else {
3763ccd8e176SBarry Smith     ierr = PetscMalloc((nnz_max+1)*sizeof(PetscScalar),&values);CHKERRQ(ierr);
3764ccd8e176SBarry Smith     ierr = PetscMemzero(values,nnz_max*sizeof(PetscScalar));CHKERRQ(ierr);
3765ccd8e176SBarry Smith   }
3766ccd8e176SBarry Smith 
3767ccd8e176SBarry Smith   for (i=0; i<m; i++) {
3768ccd8e176SBarry Smith     ii   = i + rstart;
3769b7940d39SSatish Balay     nnz  = Ii[i+1]- Ii[i];
3770b7940d39SSatish Balay     ierr = MatSetValues_MPIAIJ(B,1,&ii,nnz,J+Ii[i],values+(v ? Ii[i] : 0),INSERT_VALUES);CHKERRQ(ierr);
3771ccd8e176SBarry Smith   }
3772ccd8e176SBarry Smith   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3773ccd8e176SBarry Smith   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3774ccd8e176SBarry Smith 
3775ccd8e176SBarry Smith   if (!v) {
3776ccd8e176SBarry Smith     ierr = PetscFree(values);CHKERRQ(ierr);
3777ccd8e176SBarry Smith   }
37787827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
3779ccd8e176SBarry Smith   PetscFunctionReturn(0);
3780ccd8e176SBarry Smith }
3781e2e86b8fSSatish Balay EXTERN_C_END
3782ccd8e176SBarry Smith 
3783ccd8e176SBarry Smith #undef __FUNCT__
3784ccd8e176SBarry Smith #define __FUNCT__ "MatMPIAIJSetPreallocationCSR"
37851eea217eSSatish Balay /*@
3786ccd8e176SBarry Smith    MatMPIAIJSetPreallocationCSR - Allocates memory for a sparse parallel matrix in AIJ format
3787ccd8e176SBarry Smith    (the default parallel PETSc format).
3788ccd8e176SBarry Smith 
3789ccd8e176SBarry Smith    Collective on MPI_Comm
3790ccd8e176SBarry Smith 
3791ccd8e176SBarry Smith    Input Parameters:
3792a1661176SMatthew Knepley +  B - the matrix
3793ccd8e176SBarry Smith .  i - the indices into j for the start of each local row (starts with zero)
37940daa03b5SJed Brown .  j - the column indices for each local row (starts with zero)
3795ccd8e176SBarry Smith -  v - optional values in the matrix
3796ccd8e176SBarry Smith 
3797ccd8e176SBarry Smith    Level: developer
3798ccd8e176SBarry Smith 
379912251496SSatish Balay    Notes:
380012251496SSatish Balay        The i, j, and a arrays ARE copied by this routine into the internal format used by PETSc;
380112251496SSatish Balay      thus you CANNOT change the matrix entries by changing the values of a[] after you have
380212251496SSatish Balay      called this routine. Use MatCreateMPIAIJWithSplitArrays() to avoid needing to copy the arrays.
380312251496SSatish Balay 
380412251496SSatish Balay        The i and j indices are 0 based, and i indices are indices corresponding to the local j array.
380512251496SSatish Balay 
380612251496SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
380712251496SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
380812251496SSatish Balay     as shown:
380912251496SSatish Balay 
381012251496SSatish Balay         1 0 0
381112251496SSatish Balay         2 0 3     P0
381212251496SSatish Balay        -------
381312251496SSatish Balay         4 5 6     P1
381412251496SSatish Balay 
381512251496SSatish Balay      Process0 [P0]: rows_owned=[0,1]
381612251496SSatish Balay         i =  {0,1,3}  [size = nrow+1  = 2+1]
381712251496SSatish Balay         j =  {0,0,2}  [size = nz = 6]
381812251496SSatish Balay         v =  {1,2,3}  [size = nz = 6]
381912251496SSatish Balay 
382012251496SSatish Balay      Process1 [P1]: rows_owned=[2]
382112251496SSatish Balay         i =  {0,3}    [size = nrow+1  = 1+1]
382212251496SSatish Balay         j =  {0,1,2}  [size = nz = 6]
382312251496SSatish Balay         v =  {4,5,6}  [size = nz = 6]
382412251496SSatish Balay 
3825ccd8e176SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel
3826ccd8e176SBarry Smith 
382769b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatCreateAIJ(), MPIAIJ,
38288d7a6e47SBarry Smith           MatCreateSeqAIJWithArrays(), MatCreateMPIAIJWithSplitArrays()
3829ccd8e176SBarry Smith @*/
38307087cfbeSBarry Smith PetscErrorCode  MatMPIAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[], const PetscScalar v[])
3831ccd8e176SBarry Smith {
38324ac538c5SBarry Smith   PetscErrorCode ierr;
3833ccd8e176SBarry Smith 
3834ccd8e176SBarry Smith   PetscFunctionBegin;
38354ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatMPIAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
3836ccd8e176SBarry Smith   PetscFunctionReturn(0);
3837ccd8e176SBarry Smith }
3838ccd8e176SBarry Smith 
3839ccd8e176SBarry Smith #undef __FUNCT__
38404a2ae208SSatish Balay #define __FUNCT__ "MatMPIAIJSetPreallocation"
3841273d9f13SBarry Smith /*@C
3842ccd8e176SBarry Smith    MatMPIAIJSetPreallocation - Preallocates memory for a sparse parallel matrix in AIJ format
3843273d9f13SBarry Smith    (the default parallel PETSc format).  For good matrix assembly performance
3844273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameters
3845273d9f13SBarry Smith    d_nz (or d_nnz) and o_nz (or o_nnz).  By setting these parameters accurately,
3846273d9f13SBarry Smith    performance can be increased by more than a factor of 50.
3847273d9f13SBarry Smith 
3848273d9f13SBarry Smith    Collective on MPI_Comm
3849273d9f13SBarry Smith 
3850273d9f13SBarry Smith    Input Parameters:
3851273d9f13SBarry Smith +  A - the matrix
3852273d9f13SBarry Smith .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
3853273d9f13SBarry Smith            (same value is used for all local rows)
3854273d9f13SBarry Smith .  d_nnz - array containing the number of nonzeros in the various rows of the
3855273d9f13SBarry Smith            DIAGONAL portion of the local submatrix (possibly different for each row)
3856273d9f13SBarry Smith            or PETSC_NULL, if d_nz is used to specify the nonzero structure.
3857273d9f13SBarry Smith            The size of this array is equal to the number of local rows, i.e 'm'.
38583287b5eaSJed Brown            For matrices that will be factored, you must leave room for (and set)
38593287b5eaSJed Brown            the diagonal entry even if it is zero.
3860273d9f13SBarry Smith .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
3861273d9f13SBarry Smith            submatrix (same value is used for all local rows).
3862273d9f13SBarry Smith -  o_nnz - array containing the number of nonzeros in the various rows of the
3863273d9f13SBarry Smith            OFF-DIAGONAL portion of the local submatrix (possibly different for
3864273d9f13SBarry Smith            each row) or PETSC_NULL, if o_nz is used to specify the nonzero
3865273d9f13SBarry Smith            structure. The size of this array is equal to the number
3866273d9f13SBarry Smith            of local rows, i.e 'm'.
3867273d9f13SBarry Smith 
386849a6f317SBarry Smith    If the *_nnz parameter is given then the *_nz parameter is ignored
386949a6f317SBarry Smith 
3870273d9f13SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
3871ccd8e176SBarry Smith    compressed row storage (CSR)), is fully compatible with standard Fortran 77
38720598bfebSBarry Smith    storage.  The stored row and column indices begin with zero.
38730598bfebSBarry Smith    See the <A href="../../docs/manual.pdf#nameddest=ch_mat">Mat chapter of the users manual</A> for details.
3874273d9f13SBarry Smith 
3875273d9f13SBarry Smith    The parallel matrix is partitioned such that the first m0 rows belong to
3876273d9f13SBarry Smith    process 0, the next m1 rows belong to process 1, the next m2 rows belong
3877273d9f13SBarry Smith    to process 2 etc.. where m0,m1,m2... are the input parameter 'm'.
3878273d9f13SBarry Smith 
3879273d9f13SBarry Smith    The DIAGONAL portion of the local submatrix of a processor can be defined
3880a05b864aSJed Brown    as the submatrix which is obtained by extraction the part corresponding to
3881a05b864aSJed Brown    the rows r1-r2 and columns c1-c2 of the global matrix, where r1 is the
3882a05b864aSJed Brown    first row that belongs to the processor, r2 is the last row belonging to
3883a05b864aSJed Brown    the this processor, and c1-c2 is range of indices of the local part of a
3884a05b864aSJed Brown    vector suitable for applying the matrix to.  This is an mxn matrix.  In the
3885a05b864aSJed Brown    common case of a square matrix, the row and column ranges are the same and
3886a05b864aSJed Brown    the DIAGONAL part is also square. The remaining portion of the local
3887a05b864aSJed Brown    submatrix (mxN) constitute the OFF-DIAGONAL portion.
3888273d9f13SBarry Smith 
3889273d9f13SBarry Smith    If o_nnz, d_nnz are specified, then o_nz, and d_nz are ignored.
3890273d9f13SBarry Smith 
3891aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
3892aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3893aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
3894aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
3895aa95bbe8SBarry Smith 
3896273d9f13SBarry Smith    Example usage:
3897273d9f13SBarry Smith 
3898273d9f13SBarry Smith    Consider the following 8x8 matrix with 34 non-zero values, that is
3899273d9f13SBarry Smith    assembled across 3 processors. Lets assume that proc0 owns 3 rows,
3900273d9f13SBarry Smith    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
3901273d9f13SBarry Smith    as follows:
3902273d9f13SBarry Smith 
3903273d9f13SBarry Smith .vb
3904273d9f13SBarry Smith             1  2  0  |  0  3  0  |  0  4
3905273d9f13SBarry Smith     Proc0   0  5  6  |  7  0  0  |  8  0
3906273d9f13SBarry Smith             9  0 10  | 11  0  0  | 12  0
3907273d9f13SBarry Smith     -------------------------------------
3908273d9f13SBarry Smith            13  0 14  | 15 16 17  |  0  0
3909273d9f13SBarry Smith     Proc1   0 18  0  | 19 20 21  |  0  0
3910273d9f13SBarry Smith             0  0  0  | 22 23  0  | 24  0
3911273d9f13SBarry Smith     -------------------------------------
3912273d9f13SBarry Smith     Proc2  25 26 27  |  0  0 28  | 29  0
3913273d9f13SBarry Smith            30  0  0  | 31 32 33  |  0 34
3914273d9f13SBarry Smith .ve
3915273d9f13SBarry Smith 
3916273d9f13SBarry Smith    This can be represented as a collection of submatrices as:
3917273d9f13SBarry Smith 
3918273d9f13SBarry Smith .vb
3919273d9f13SBarry Smith       A B C
3920273d9f13SBarry Smith       D E F
3921273d9f13SBarry Smith       G H I
3922273d9f13SBarry Smith .ve
3923273d9f13SBarry Smith 
3924273d9f13SBarry Smith    Where the submatrices A,B,C are owned by proc0, D,E,F are
3925273d9f13SBarry Smith    owned by proc1, G,H,I are owned by proc2.
3926273d9f13SBarry Smith 
3927273d9f13SBarry Smith    The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
3928273d9f13SBarry Smith    The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
3929273d9f13SBarry Smith    The 'M','N' parameters are 8,8, and have the same values on all procs.
3930273d9f13SBarry Smith 
3931273d9f13SBarry Smith    The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are
3932273d9f13SBarry Smith    submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices
3933273d9f13SBarry Smith    corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively.
3934273d9f13SBarry Smith    Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL
3935273d9f13SBarry Smith    part as SeqAIJ matrices. for eg: proc1 will store [E] as a SeqAIJ
3936273d9f13SBarry Smith    matrix, ans [DF] as another SeqAIJ matrix.
3937273d9f13SBarry Smith 
3938273d9f13SBarry Smith    When d_nz, o_nz parameters are specified, d_nz storage elements are
3939273d9f13SBarry Smith    allocated for every row of the local diagonal submatrix, and o_nz
3940273d9f13SBarry Smith    storage locations are allocated for every row of the OFF-DIAGONAL submat.
3941273d9f13SBarry Smith    One way to choose d_nz and o_nz is to use the max nonzerors per local
3942273d9f13SBarry Smith    rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices.
3943273d9f13SBarry Smith    In this case, the values of d_nz,o_nz are:
3944273d9f13SBarry Smith .vb
3945273d9f13SBarry Smith      proc0 : dnz = 2, o_nz = 2
3946273d9f13SBarry Smith      proc1 : dnz = 3, o_nz = 2
3947273d9f13SBarry Smith      proc2 : dnz = 1, o_nz = 4
3948273d9f13SBarry Smith .ve
3949273d9f13SBarry Smith    We are allocating m*(d_nz+o_nz) storage locations for every proc. This
3950273d9f13SBarry Smith    translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10
3951273d9f13SBarry Smith    for proc3. i.e we are using 12+15+10=37 storage locations to store
3952273d9f13SBarry Smith    34 values.
3953273d9f13SBarry Smith 
3954273d9f13SBarry Smith    When d_nnz, o_nnz parameters are specified, the storage is specified
3955273d9f13SBarry Smith    for every row, coresponding to both DIAGONAL and OFF-DIAGONAL submatrices.
3956273d9f13SBarry Smith    In the above case the values for d_nnz,o_nnz are:
3957273d9f13SBarry Smith .vb
3958273d9f13SBarry Smith      proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2]
3959273d9f13SBarry Smith      proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1]
3960273d9f13SBarry Smith      proc2: d_nnz = [1,1]   and o_nnz = [4,4]
3961273d9f13SBarry Smith .ve
3962273d9f13SBarry Smith    Here the space allocated is sum of all the above values i.e 34, and
3963273d9f13SBarry Smith    hence pre-allocation is perfect.
3964273d9f13SBarry Smith 
3965273d9f13SBarry Smith    Level: intermediate
3966273d9f13SBarry Smith 
3967273d9f13SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel
3968273d9f13SBarry Smith 
396969b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateAIJ(), MatMPIAIJSetPreallocationCSR(),
3970aa95bbe8SBarry Smith           MPIAIJ, MatGetInfo()
3971273d9f13SBarry Smith @*/
39727087cfbeSBarry Smith PetscErrorCode  MatMPIAIJSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
3973273d9f13SBarry Smith {
39744ac538c5SBarry Smith   PetscErrorCode ierr;
3975273d9f13SBarry Smith 
3976273d9f13SBarry Smith   PetscFunctionBegin;
39776ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
39786ba663aaSJed Brown   PetscValidType(B,1);
39794ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatMPIAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
3980273d9f13SBarry Smith   PetscFunctionReturn(0);
3981273d9f13SBarry Smith }
3982273d9f13SBarry Smith 
39834a2ae208SSatish Balay #undef __FUNCT__
39842fb0ec9aSBarry Smith #define __FUNCT__ "MatCreateMPIAIJWithArrays"
398558d36128SBarry Smith /*@
39862fb0ec9aSBarry Smith      MatCreateMPIAIJWithArrays - creates a MPI AIJ matrix using arrays that contain in standard
39872fb0ec9aSBarry Smith          CSR format the local rows.
39882fb0ec9aSBarry Smith 
39892fb0ec9aSBarry Smith    Collective on MPI_Comm
39902fb0ec9aSBarry Smith 
39912fb0ec9aSBarry Smith    Input Parameters:
39922fb0ec9aSBarry Smith +  comm - MPI communicator
39932fb0ec9aSBarry Smith .  m - number of local rows (Cannot be PETSC_DECIDE)
39942fb0ec9aSBarry Smith .  n - This value should be the same as the local size used in creating the
39952fb0ec9aSBarry Smith        x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have
39962fb0ec9aSBarry Smith        calculated if N is given) For square matrices n is almost always m.
39972fb0ec9aSBarry Smith .  M - number of global rows (or PETSC_DETERMINE to have calculated if m is given)
39982fb0ec9aSBarry Smith .  N - number of global columns (or PETSC_DETERMINE to have calculated if n is given)
39992fb0ec9aSBarry Smith .   i - row indices
40002fb0ec9aSBarry Smith .   j - column indices
40012fb0ec9aSBarry Smith -   a - matrix values
40022fb0ec9aSBarry Smith 
40032fb0ec9aSBarry Smith    Output Parameter:
40042fb0ec9aSBarry Smith .   mat - the matrix
400503bfb495SBarry Smith 
40062fb0ec9aSBarry Smith    Level: intermediate
40072fb0ec9aSBarry Smith 
40082fb0ec9aSBarry Smith    Notes:
40092fb0ec9aSBarry Smith        The i, j, and a arrays ARE copied by this routine into the internal format used by PETSc;
40102fb0ec9aSBarry Smith      thus you CANNOT change the matrix entries by changing the values of a[] after you have
40118d7a6e47SBarry Smith      called this routine. Use MatCreateMPIAIJWithSplitArrays() to avoid needing to copy the arrays.
40122fb0ec9aSBarry Smith 
401312251496SSatish Balay        The i and j indices are 0 based, and i indices are indices corresponding to the local j array.
401412251496SSatish Balay 
401512251496SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
401612251496SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
401712251496SSatish Balay     as shown:
401812251496SSatish Balay 
401912251496SSatish Balay         1 0 0
402012251496SSatish Balay         2 0 3     P0
402112251496SSatish Balay        -------
402212251496SSatish Balay         4 5 6     P1
402312251496SSatish Balay 
402412251496SSatish Balay      Process0 [P0]: rows_owned=[0,1]
402512251496SSatish Balay         i =  {0,1,3}  [size = nrow+1  = 2+1]
402612251496SSatish Balay         j =  {0,0,2}  [size = nz = 6]
402712251496SSatish Balay         v =  {1,2,3}  [size = nz = 6]
402812251496SSatish Balay 
402912251496SSatish Balay      Process1 [P1]: rows_owned=[2]
403012251496SSatish Balay         i =  {0,3}    [size = nrow+1  = 1+1]
403112251496SSatish Balay         j =  {0,1,2}  [size = nz = 6]
403212251496SSatish Balay         v =  {4,5,6}  [size = nz = 6]
40332fb0ec9aSBarry Smith 
40342fb0ec9aSBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel
40352fb0ec9aSBarry Smith 
40362fb0ec9aSBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(),
403769b1f4b7SBarry Smith           MPIAIJ, MatCreateAIJ(), MatCreateMPIAIJWithSplitArrays()
40382fb0ec9aSBarry Smith @*/
40397087cfbeSBarry Smith PetscErrorCode  MatCreateMPIAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,const PetscInt i[],const PetscInt j[],const PetscScalar a[],Mat *mat)
40402fb0ec9aSBarry Smith {
40412fb0ec9aSBarry Smith   PetscErrorCode ierr;
40422fb0ec9aSBarry Smith 
40432fb0ec9aSBarry Smith   PetscFunctionBegin;
404469b1f4b7SBarry Smith   if (i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4045e32f2f54SBarry Smith   if (m < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"local number of rows (m) cannot be PETSC_DECIDE, or negative");
40462fb0ec9aSBarry Smith   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
4047d4146a68SBarry Smith   ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr);
4048a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(M,bs,cbs); CHKERRQ(ierr); */
40492fb0ec9aSBarry Smith   ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr);
40502fb0ec9aSBarry Smith   ierr = MatMPIAIJSetPreallocationCSR(*mat,i,j,a);CHKERRQ(ierr);
40512fb0ec9aSBarry Smith   PetscFunctionReturn(0);
40522fb0ec9aSBarry Smith }
40532fb0ec9aSBarry Smith 
40542fb0ec9aSBarry Smith #undef __FUNCT__
405569b1f4b7SBarry Smith #define __FUNCT__ "MatCreateAIJ"
4056273d9f13SBarry Smith /*@C
405769b1f4b7SBarry Smith    MatCreateAIJ - Creates a sparse parallel matrix in AIJ format
4058273d9f13SBarry Smith    (the default parallel PETSc format).  For good matrix assembly performance
4059273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameters
4060273d9f13SBarry Smith    d_nz (or d_nnz) and o_nz (or o_nnz).  By setting these parameters accurately,
4061273d9f13SBarry Smith    performance can be increased by more than a factor of 50.
4062273d9f13SBarry Smith 
4063273d9f13SBarry Smith    Collective on MPI_Comm
4064273d9f13SBarry Smith 
4065273d9f13SBarry Smith    Input Parameters:
4066273d9f13SBarry Smith +  comm - MPI communicator
4067273d9f13SBarry Smith .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
4068273d9f13SBarry Smith            This value should be the same as the local size used in creating the
4069273d9f13SBarry Smith            y vector for the matrix-vector product y = Ax.
4070273d9f13SBarry Smith .  n - This value should be the same as the local size used in creating the
4071273d9f13SBarry Smith        x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have
4072273d9f13SBarry Smith        calculated if N is given) For square matrices n is almost always m.
4073273d9f13SBarry Smith .  M - number of global rows (or PETSC_DETERMINE to have calculated if m is given)
4074273d9f13SBarry Smith .  N - number of global columns (or PETSC_DETERMINE to have calculated if n is given)
4075273d9f13SBarry Smith .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
4076273d9f13SBarry Smith            (same value is used for all local rows)
4077273d9f13SBarry Smith .  d_nnz - array containing the number of nonzeros in the various rows of the
4078273d9f13SBarry Smith            DIAGONAL portion of the local submatrix (possibly different for each row)
4079273d9f13SBarry Smith            or PETSC_NULL, if d_nz is used to specify the nonzero structure.
4080273d9f13SBarry Smith            The size of this array is equal to the number of local rows, i.e 'm'.
4081273d9f13SBarry Smith .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
4082273d9f13SBarry Smith            submatrix (same value is used for all local rows).
4083273d9f13SBarry Smith -  o_nnz - array containing the number of nonzeros in the various rows of the
4084273d9f13SBarry Smith            OFF-DIAGONAL portion of the local submatrix (possibly different for
4085273d9f13SBarry Smith            each row) or PETSC_NULL, if o_nz is used to specify the nonzero
4086273d9f13SBarry Smith            structure. The size of this array is equal to the number
4087273d9f13SBarry Smith            of local rows, i.e 'm'.
4088273d9f13SBarry Smith 
4089273d9f13SBarry Smith    Output Parameter:
4090273d9f13SBarry Smith .  A - the matrix
4091273d9f13SBarry Smith 
4092175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
4093ae1d86c5SBarry Smith    MatXXXXSetPreallocation() paradgm instead of this routine directly.
4094175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
4095175b88e8SBarry Smith 
4096273d9f13SBarry Smith    Notes:
409749a6f317SBarry Smith    If the *_nnz parameter is given then the *_nz parameter is ignored
409849a6f317SBarry Smith 
4099273d9f13SBarry Smith    m,n,M,N parameters specify the size of the matrix, and its partitioning across
4100273d9f13SBarry Smith    processors, while d_nz,d_nnz,o_nz,o_nnz parameters specify the approximate
4101273d9f13SBarry Smith    storage requirements for this matrix.
4102273d9f13SBarry Smith 
4103273d9f13SBarry Smith    If PETSC_DECIDE or  PETSC_DETERMINE is used for a particular argument on one
4104273d9f13SBarry Smith    processor than it must be used on all processors that share the object for
4105273d9f13SBarry Smith    that argument.
4106273d9f13SBarry Smith 
4107273d9f13SBarry Smith    The user MUST specify either the local or global matrix dimensions
4108273d9f13SBarry Smith    (possibly both).
4109273d9f13SBarry Smith 
411033a7c187SSatish Balay    The parallel matrix is partitioned across processors such that the
411133a7c187SSatish Balay    first m0 rows belong to process 0, the next m1 rows belong to
411233a7c187SSatish Balay    process 1, the next m2 rows belong to process 2 etc.. where
411333a7c187SSatish Balay    m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores
411433a7c187SSatish Balay    values corresponding to [m x N] submatrix.
4115273d9f13SBarry Smith 
411633a7c187SSatish Balay    The columns are logically partitioned with the n0 columns belonging
411733a7c187SSatish Balay    to 0th partition, the next n1 columns belonging to the next
411833a7c187SSatish Balay    partition etc.. where n0,n1,n2... are the the input parameter 'n'.
411933a7c187SSatish Balay 
412033a7c187SSatish Balay    The DIAGONAL portion of the local submatrix on any given processor
412133a7c187SSatish Balay    is the submatrix corresponding to the rows and columns m,n
412233a7c187SSatish Balay    corresponding to the given processor. i.e diagonal matrix on
412333a7c187SSatish Balay    process 0 is [m0 x n0], diagonal matrix on process 1 is [m1 x n1]
412433a7c187SSatish Balay    etc. The remaining portion of the local submatrix [m x (N-n)]
412533a7c187SSatish Balay    constitute the OFF-DIAGONAL portion. The example below better
412633a7c187SSatish Balay    illustrates this concept.
412733a7c187SSatish Balay 
412833a7c187SSatish Balay    For a square global matrix we define each processor's diagonal portion
412933a7c187SSatish Balay    to be its local rows and the corresponding columns (a square submatrix);
413033a7c187SSatish Balay    each processor's off-diagonal portion encompasses the remainder of the
413133a7c187SSatish Balay    local matrix (a rectangular submatrix).
4132273d9f13SBarry Smith 
4133273d9f13SBarry Smith    If o_nnz, d_nnz are specified, then o_nz, and d_nz are ignored.
4134273d9f13SBarry Smith 
413597d05335SKris Buschelman    When calling this routine with a single process communicator, a matrix of
413697d05335SKris Buschelman    type SEQAIJ is returned.  If a matrix of type MPIAIJ is desired for this
413797d05335SKris Buschelman    type of communicator, use the construction mechanism:
413878102f6cSMatthew Knepley      MatCreate(...,&A); MatSetType(A,MATMPIAIJ); MatSetSizes(A, m,n,M,N); MatMPIAIJSetPreallocation(A,...);
413997d05335SKris Buschelman 
4140273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible.
4141273d9f13SBarry Smith    We search for consecutive rows with the same nonzero structure, thereby
4142273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
4143273d9f13SBarry Smith 
4144273d9f13SBarry Smith    Options Database Keys:
4145923f20ffSKris Buschelman +  -mat_no_inode  - Do not use inodes
4146923f20ffSKris Buschelman .  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
4147273d9f13SBarry Smith -  -mat_aij_oneindex - Internally use indexing starting at 1
4148273d9f13SBarry Smith         rather than 0.  Note that when calling MatSetValues(),
4149273d9f13SBarry Smith         the user still MUST index entries starting at 0!
4150273d9f13SBarry Smith 
4151273d9f13SBarry Smith 
4152273d9f13SBarry Smith    Example usage:
4153273d9f13SBarry Smith 
4154273d9f13SBarry Smith    Consider the following 8x8 matrix with 34 non-zero values, that is
4155273d9f13SBarry Smith    assembled across 3 processors. Lets assume that proc0 owns 3 rows,
4156273d9f13SBarry Smith    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
4157273d9f13SBarry Smith    as follows:
4158273d9f13SBarry Smith 
4159273d9f13SBarry Smith .vb
4160273d9f13SBarry Smith             1  2  0  |  0  3  0  |  0  4
4161273d9f13SBarry Smith     Proc0   0  5  6  |  7  0  0  |  8  0
4162273d9f13SBarry Smith             9  0 10  | 11  0  0  | 12  0
4163273d9f13SBarry Smith     -------------------------------------
4164273d9f13SBarry Smith            13  0 14  | 15 16 17  |  0  0
4165273d9f13SBarry Smith     Proc1   0 18  0  | 19 20 21  |  0  0
4166273d9f13SBarry Smith             0  0  0  | 22 23  0  | 24  0
4167273d9f13SBarry Smith     -------------------------------------
4168273d9f13SBarry Smith     Proc2  25 26 27  |  0  0 28  | 29  0
4169273d9f13SBarry Smith            30  0  0  | 31 32 33  |  0 34
4170273d9f13SBarry Smith .ve
4171273d9f13SBarry Smith 
4172273d9f13SBarry Smith    This can be represented as a collection of submatrices as:
4173273d9f13SBarry Smith 
4174273d9f13SBarry Smith .vb
4175273d9f13SBarry Smith       A B C
4176273d9f13SBarry Smith       D E F
4177273d9f13SBarry Smith       G H I
4178273d9f13SBarry Smith .ve
4179273d9f13SBarry Smith 
4180273d9f13SBarry Smith    Where the submatrices A,B,C are owned by proc0, D,E,F are
4181273d9f13SBarry Smith    owned by proc1, G,H,I are owned by proc2.
4182273d9f13SBarry Smith 
4183273d9f13SBarry Smith    The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
4184273d9f13SBarry Smith    The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
4185273d9f13SBarry Smith    The 'M','N' parameters are 8,8, and have the same values on all procs.
4186273d9f13SBarry Smith 
4187273d9f13SBarry Smith    The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are
4188273d9f13SBarry Smith    submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices
4189273d9f13SBarry Smith    corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively.
4190273d9f13SBarry Smith    Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL
4191273d9f13SBarry Smith    part as SeqAIJ matrices. for eg: proc1 will store [E] as a SeqAIJ
4192273d9f13SBarry Smith    matrix, ans [DF] as another SeqAIJ matrix.
4193273d9f13SBarry Smith 
4194273d9f13SBarry Smith    When d_nz, o_nz parameters are specified, d_nz storage elements are
4195273d9f13SBarry Smith    allocated for every row of the local diagonal submatrix, and o_nz
4196273d9f13SBarry Smith    storage locations are allocated for every row of the OFF-DIAGONAL submat.
4197273d9f13SBarry Smith    One way to choose d_nz and o_nz is to use the max nonzerors per local
4198273d9f13SBarry Smith    rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices.
4199273d9f13SBarry Smith    In this case, the values of d_nz,o_nz are:
4200273d9f13SBarry Smith .vb
4201273d9f13SBarry Smith      proc0 : dnz = 2, o_nz = 2
4202273d9f13SBarry Smith      proc1 : dnz = 3, o_nz = 2
4203273d9f13SBarry Smith      proc2 : dnz = 1, o_nz = 4
4204273d9f13SBarry Smith .ve
4205273d9f13SBarry Smith    We are allocating m*(d_nz+o_nz) storage locations for every proc. This
4206273d9f13SBarry Smith    translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10
4207273d9f13SBarry Smith    for proc3. i.e we are using 12+15+10=37 storage locations to store
4208273d9f13SBarry Smith    34 values.
4209273d9f13SBarry Smith 
4210273d9f13SBarry Smith    When d_nnz, o_nnz parameters are specified, the storage is specified
4211273d9f13SBarry Smith    for every row, coresponding to both DIAGONAL and OFF-DIAGONAL submatrices.
4212273d9f13SBarry Smith    In the above case the values for d_nnz,o_nnz are:
4213273d9f13SBarry Smith .vb
4214273d9f13SBarry Smith      proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2]
4215273d9f13SBarry Smith      proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1]
4216273d9f13SBarry Smith      proc2: d_nnz = [1,1]   and o_nnz = [4,4]
4217273d9f13SBarry Smith .ve
4218273d9f13SBarry Smith    Here the space allocated is sum of all the above values i.e 34, and
4219273d9f13SBarry Smith    hence pre-allocation is perfect.
4220273d9f13SBarry Smith 
4221273d9f13SBarry Smith    Level: intermediate
4222273d9f13SBarry Smith 
4223273d9f13SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel
4224273d9f13SBarry Smith 
4225ccd8e176SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(),
42262fb0ec9aSBarry Smith           MPIAIJ, MatCreateMPIAIJWithArrays()
4227273d9f13SBarry Smith @*/
422869b1f4b7SBarry Smith PetscErrorCode  MatCreateAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[],Mat *A)
4229273d9f13SBarry Smith {
42306849ba73SBarry Smith   PetscErrorCode ierr;
4231b1d57f15SBarry Smith   PetscMPIInt    size;
4232273d9f13SBarry Smith 
4233273d9f13SBarry Smith   PetscFunctionBegin;
4234f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
4235f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
4236273d9f13SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
4237273d9f13SBarry Smith   if (size > 1) {
4238273d9f13SBarry Smith     ierr = MatSetType(*A,MATMPIAIJ);CHKERRQ(ierr);
4239273d9f13SBarry Smith     ierr = MatMPIAIJSetPreallocation(*A,d_nz,d_nnz,o_nz,o_nnz);CHKERRQ(ierr);
4240273d9f13SBarry Smith   } else {
4241273d9f13SBarry Smith     ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
4242273d9f13SBarry Smith     ierr = MatSeqAIJSetPreallocation(*A,d_nz,d_nnz);CHKERRQ(ierr);
4243273d9f13SBarry Smith   }
4244273d9f13SBarry Smith   PetscFunctionReturn(0);
4245273d9f13SBarry Smith }
4246195d93cdSBarry Smith 
42474a2ae208SSatish Balay #undef __FUNCT__
42484a2ae208SSatish Balay #define __FUNCT__ "MatMPIAIJGetSeqAIJ"
42497087cfbeSBarry Smith PetscErrorCode  MatMPIAIJGetSeqAIJ(Mat A,Mat *Ad,Mat *Ao,PetscInt *colmap[])
4250195d93cdSBarry Smith {
4251195d93cdSBarry Smith   Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data;
4252b1d57f15SBarry Smith 
4253195d93cdSBarry Smith   PetscFunctionBegin;
4254195d93cdSBarry Smith   *Ad     = a->A;
4255195d93cdSBarry Smith   *Ao     = a->B;
4256195d93cdSBarry Smith   *colmap = a->garray;
4257195d93cdSBarry Smith   PetscFunctionReturn(0);
4258195d93cdSBarry Smith }
4259a2243be0SBarry Smith 
4260a2243be0SBarry Smith #undef __FUNCT__
4261a2243be0SBarry Smith #define __FUNCT__ "MatSetColoring_MPIAIJ"
4262dfbe8321SBarry Smith PetscErrorCode MatSetColoring_MPIAIJ(Mat A,ISColoring coloring)
4263a2243be0SBarry Smith {
4264dfbe8321SBarry Smith   PetscErrorCode ierr;
4265b1d57f15SBarry Smith   PetscInt       i;
4266a2243be0SBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
4267a2243be0SBarry Smith 
4268a2243be0SBarry Smith   PetscFunctionBegin;
42698ee2e534SBarry Smith   if (coloring->ctype == IS_COLORING_GLOBAL) {
427008b6dcc0SBarry Smith     ISColoringValue *allcolors,*colors;
4271a2243be0SBarry Smith     ISColoring      ocoloring;
4272a2243be0SBarry Smith 
4273a2243be0SBarry Smith     /* set coloring for diagonal portion */
4274a2243be0SBarry Smith     ierr = MatSetColoring_SeqAIJ(a->A,coloring);CHKERRQ(ierr);
4275a2243be0SBarry Smith 
4276a2243be0SBarry Smith     /* set coloring for off-diagonal portion */
42777adad957SLisandro Dalcin     ierr = ISAllGatherColors(((PetscObject)A)->comm,coloring->n,coloring->colors,PETSC_NULL,&allcolors);CHKERRQ(ierr);
4278d0f46423SBarry Smith     ierr = PetscMalloc((a->B->cmap->n+1)*sizeof(ISColoringValue),&colors);CHKERRQ(ierr);
4279d0f46423SBarry Smith     for (i=0; i<a->B->cmap->n; i++) {
4280a2243be0SBarry Smith       colors[i] = allcolors[a->garray[i]];
4281a2243be0SBarry Smith     }
4282a2243be0SBarry Smith     ierr = PetscFree(allcolors);CHKERRQ(ierr);
4283d0f46423SBarry Smith     ierr = ISColoringCreate(MPI_COMM_SELF,coloring->n,a->B->cmap->n,colors,&ocoloring);CHKERRQ(ierr);
4284a2243be0SBarry Smith     ierr = MatSetColoring_SeqAIJ(a->B,ocoloring);CHKERRQ(ierr);
42856bf464f9SBarry Smith     ierr = ISColoringDestroy(&ocoloring);CHKERRQ(ierr);
4286a2243be0SBarry Smith   } else if (coloring->ctype == IS_COLORING_GHOSTED) {
428708b6dcc0SBarry Smith     ISColoringValue *colors;
4288b1d57f15SBarry Smith     PetscInt        *larray;
4289a2243be0SBarry Smith     ISColoring      ocoloring;
4290a2243be0SBarry Smith 
4291a2243be0SBarry Smith     /* set coloring for diagonal portion */
4292d0f46423SBarry Smith     ierr = PetscMalloc((a->A->cmap->n+1)*sizeof(PetscInt),&larray);CHKERRQ(ierr);
4293d0f46423SBarry Smith     for (i=0; i<a->A->cmap->n; i++) {
4294d0f46423SBarry Smith       larray[i] = i + A->cmap->rstart;
4295a2243be0SBarry Smith     }
4296992144d0SBarry Smith     ierr = ISGlobalToLocalMappingApply(A->cmap->mapping,IS_GTOLM_MASK,a->A->cmap->n,larray,PETSC_NULL,larray);CHKERRQ(ierr);
4297d0f46423SBarry Smith     ierr = PetscMalloc((a->A->cmap->n+1)*sizeof(ISColoringValue),&colors);CHKERRQ(ierr);
4298d0f46423SBarry Smith     for (i=0; i<a->A->cmap->n; i++) {
4299a2243be0SBarry Smith       colors[i] = coloring->colors[larray[i]];
4300a2243be0SBarry Smith     }
4301a2243be0SBarry Smith     ierr = PetscFree(larray);CHKERRQ(ierr);
4302d0f46423SBarry Smith     ierr = ISColoringCreate(PETSC_COMM_SELF,coloring->n,a->A->cmap->n,colors,&ocoloring);CHKERRQ(ierr);
4303a2243be0SBarry Smith     ierr = MatSetColoring_SeqAIJ(a->A,ocoloring);CHKERRQ(ierr);
43046bf464f9SBarry Smith     ierr = ISColoringDestroy(&ocoloring);CHKERRQ(ierr);
4305a2243be0SBarry Smith 
4306a2243be0SBarry Smith     /* set coloring for off-diagonal portion */
4307d0f46423SBarry Smith     ierr = PetscMalloc((a->B->cmap->n+1)*sizeof(PetscInt),&larray);CHKERRQ(ierr);
4308992144d0SBarry Smith     ierr = ISGlobalToLocalMappingApply(A->cmap->mapping,IS_GTOLM_MASK,a->B->cmap->n,a->garray,PETSC_NULL,larray);CHKERRQ(ierr);
4309d0f46423SBarry Smith     ierr = PetscMalloc((a->B->cmap->n+1)*sizeof(ISColoringValue),&colors);CHKERRQ(ierr);
4310d0f46423SBarry Smith     for (i=0; i<a->B->cmap->n; i++) {
4311a2243be0SBarry Smith       colors[i] = coloring->colors[larray[i]];
4312a2243be0SBarry Smith     }
4313a2243be0SBarry Smith     ierr = PetscFree(larray);CHKERRQ(ierr);
4314d0f46423SBarry Smith     ierr = ISColoringCreate(MPI_COMM_SELF,coloring->n,a->B->cmap->n,colors,&ocoloring);CHKERRQ(ierr);
4315a2243be0SBarry Smith     ierr = MatSetColoring_SeqAIJ(a->B,ocoloring);CHKERRQ(ierr);
43166bf464f9SBarry Smith     ierr = ISColoringDestroy(&ocoloring);CHKERRQ(ierr);
43176bf464f9SBarry Smith   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support ISColoringType %d",(int)coloring->ctype);
4318a2243be0SBarry Smith 
4319a2243be0SBarry Smith   PetscFunctionReturn(0);
4320a2243be0SBarry Smith }
4321a2243be0SBarry Smith 
4322dcf5cc72SBarry Smith #if defined(PETSC_HAVE_ADIC)
4323a2243be0SBarry Smith #undef __FUNCT__
4324779c1a83SBarry Smith #define __FUNCT__ "MatSetValuesAdic_MPIAIJ"
4325dfbe8321SBarry Smith PetscErrorCode MatSetValuesAdic_MPIAIJ(Mat A,void *advalues)
4326a2243be0SBarry Smith {
4327a2243be0SBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
4328dfbe8321SBarry Smith   PetscErrorCode ierr;
4329a2243be0SBarry Smith 
4330a2243be0SBarry Smith   PetscFunctionBegin;
4331779c1a83SBarry Smith   ierr = MatSetValuesAdic_SeqAIJ(a->A,advalues);CHKERRQ(ierr);
4332779c1a83SBarry Smith   ierr = MatSetValuesAdic_SeqAIJ(a->B,advalues);CHKERRQ(ierr);
4333779c1a83SBarry Smith   PetscFunctionReturn(0);
4334779c1a83SBarry Smith }
4335dcf5cc72SBarry Smith #endif
4336779c1a83SBarry Smith 
4337779c1a83SBarry Smith #undef __FUNCT__
4338779c1a83SBarry Smith #define __FUNCT__ "MatSetValuesAdifor_MPIAIJ"
4339b1d57f15SBarry Smith PetscErrorCode MatSetValuesAdifor_MPIAIJ(Mat A,PetscInt nl,void *advalues)
4340779c1a83SBarry Smith {
4341779c1a83SBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
4342dfbe8321SBarry Smith   PetscErrorCode ierr;
4343779c1a83SBarry Smith 
4344779c1a83SBarry Smith   PetscFunctionBegin;
4345779c1a83SBarry Smith   ierr = MatSetValuesAdifor_SeqAIJ(a->A,nl,advalues);CHKERRQ(ierr);
4346779c1a83SBarry Smith   ierr = MatSetValuesAdifor_SeqAIJ(a->B,nl,advalues);CHKERRQ(ierr);
4347a2243be0SBarry Smith   PetscFunctionReturn(0);
4348a2243be0SBarry Smith }
4349c5d6d63eSBarry Smith 
4350c5d6d63eSBarry Smith #undef __FUNCT__
435190431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJConcatenateSeqAIJSymbolic"
435290431a8fSHong Zhang PetscErrorCode  MatCreateMPIAIJConcatenateSeqAIJSymbolic(MPI_Comm comm,Mat inmat,PetscInt n,Mat *outmat)
43539b8102ccSHong Zhang {
43549b8102ccSHong Zhang   PetscErrorCode ierr;
4355a2f3521dSMark F. Adams   PetscInt       m,N,i,rstart,nnz,*dnz,*onz,sum,bs,cbs;
43569b8102ccSHong Zhang   PetscInt       *indx;
43579b8102ccSHong Zhang 
43589b8102ccSHong Zhang   PetscFunctionBegin;
43599b8102ccSHong Zhang   /* This routine will ONLY return MPIAIJ type matrix */
43609b8102ccSHong Zhang   ierr = MatGetSize(inmat,&m,&N);CHKERRQ(ierr);
4361a2f3521dSMark F. Adams   ierr = MatGetBlockSizes(inmat,&bs,&cbs);CHKERRQ(ierr);
43629b8102ccSHong Zhang   if (n == PETSC_DECIDE){
43639b8102ccSHong Zhang     ierr = PetscSplitOwnership(comm,&n,&N);CHKERRQ(ierr);
43649b8102ccSHong Zhang   }
4365a22543b6SHong Zhang   /* Check sum(n) = N */
4366a95133b1SBarry Smith   ierr = MPI_Allreduce(&n,&sum,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
4367a22543b6SHong Zhang   if (sum != N) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Sum of local columns != global columns %d",N);
4368a22543b6SHong Zhang 
43699b8102ccSHong Zhang   ierr = MPI_Scan(&m, &rstart,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
43709b8102ccSHong Zhang   rstart -= m;
43719b8102ccSHong Zhang 
43729b8102ccSHong Zhang   ierr = MatPreallocateInitialize(comm,m,n,dnz,onz);CHKERRQ(ierr);
43739b8102ccSHong Zhang   for (i=0;i<m;i++) {
43749b8102ccSHong Zhang     ierr = MatGetRow_SeqAIJ(inmat,i,&nnz,&indx,PETSC_NULL);CHKERRQ(ierr);
43759b8102ccSHong Zhang     ierr = MatPreallocateSet(i+rstart,nnz,indx,dnz,onz);CHKERRQ(ierr);
43769b8102ccSHong Zhang     ierr = MatRestoreRow_SeqAIJ(inmat,i,&nnz,&indx,PETSC_NULL);CHKERRQ(ierr);
43779b8102ccSHong Zhang   }
43789b8102ccSHong Zhang 
43799b8102ccSHong Zhang   ierr = MatCreate(comm,outmat);CHKERRQ(ierr);
43809b8102ccSHong Zhang   ierr = MatSetSizes(*outmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE); CHKERRQ(ierr);
4381a2f3521dSMark F. Adams   ierr = MatSetBlockSizes(*outmat,bs,cbs); CHKERRQ(ierr);
43829b8102ccSHong Zhang   ierr = MatSetType(*outmat,MATMPIAIJ);  CHKERRQ(ierr);
43839b8102ccSHong Zhang   ierr = MatMPIAIJSetPreallocation(*outmat,0,dnz,0,onz);CHKERRQ(ierr);
43849b8102ccSHong Zhang   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
43859b8102ccSHong Zhang   PetscFunctionReturn(0);
43869b8102ccSHong Zhang }
43879b8102ccSHong Zhang 
43889b8102ccSHong Zhang #undef __FUNCT__
438990431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJConcatenateSeqAIJNumeric"
439090431a8fSHong Zhang PetscErrorCode  MatCreateMPIAIJConcatenateSeqAIJNumeric(MPI_Comm comm,Mat inmat,PetscInt n,Mat outmat)
43919b8102ccSHong Zhang {
43929b8102ccSHong Zhang   PetscErrorCode ierr;
43939b8102ccSHong Zhang   PetscInt       m,N,i,rstart,nnz,Ii;
43949b8102ccSHong Zhang   PetscInt       *indx;
43959b8102ccSHong Zhang   PetscScalar    *values;
43969b8102ccSHong Zhang 
43979b8102ccSHong Zhang   PetscFunctionBegin;
43989b8102ccSHong Zhang   ierr = MatGetSize(inmat,&m,&N);CHKERRQ(ierr);
43999b8102ccSHong Zhang   ierr = MatGetOwnershipRange(outmat,&rstart,PETSC_NULL);CHKERRQ(ierr);
44009b8102ccSHong Zhang   for (i=0;i<m;i++) {
44019b8102ccSHong Zhang     ierr = MatGetRow_SeqAIJ(inmat,i,&nnz,&indx,&values);CHKERRQ(ierr);
44029b8102ccSHong Zhang     Ii    = i + rstart;
4403a22543b6SHong Zhang     ierr = MatSetValues_MPIAIJ(outmat,1,&Ii,nnz,indx,values,INSERT_VALUES);CHKERRQ(ierr);
44049b8102ccSHong Zhang     ierr = MatRestoreRow_SeqAIJ(inmat,i,&nnz,&indx,&values);CHKERRQ(ierr);
44059b8102ccSHong Zhang   }
44069b8102ccSHong Zhang   ierr = MatAssemblyBegin(outmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
44079b8102ccSHong Zhang   ierr = MatAssemblyEnd(outmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
44089b8102ccSHong Zhang   PetscFunctionReturn(0);
44099b8102ccSHong Zhang }
44109b8102ccSHong Zhang 
44119b8102ccSHong Zhang #undef __FUNCT__
441290431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJConcatenateSeqAIJ"
4413bc08b0f1SBarry Smith /*@
441490431a8fSHong Zhang       MatCreateMPIAIJConcatenateSeqAIJ - Creates a single large PETSc matrix by concatenating sequential
441551dd7536SBarry Smith                  matrices from each processor
4416c5d6d63eSBarry Smith 
4417c5d6d63eSBarry Smith     Collective on MPI_Comm
4418c5d6d63eSBarry Smith 
4419c5d6d63eSBarry Smith    Input Parameters:
442051dd7536SBarry Smith +    comm - the communicators the parallel matrix will live on
4421d6bb3c2dSHong Zhang .    inmat - the input sequential matrices
44220e36024fSHong Zhang .    n - number of local columns (or PETSC_DECIDE)
4423d6bb3c2dSHong Zhang -    scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
442451dd7536SBarry Smith 
442551dd7536SBarry Smith    Output Parameter:
442651dd7536SBarry Smith .    outmat - the parallel matrix generated
4427c5d6d63eSBarry Smith 
44287e25d530SSatish Balay     Level: advanced
44297e25d530SSatish Balay 
4430f08fae4eSHong Zhang    Notes: The number of columns of the matrix in EACH processor MUST be the same.
4431c5d6d63eSBarry Smith 
4432c5d6d63eSBarry Smith @*/
443390431a8fSHong Zhang PetscErrorCode  MatCreateMPIAIJConcatenateSeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
4434c5d6d63eSBarry Smith {
4435dfbe8321SBarry Smith   PetscErrorCode ierr;
4436c5d6d63eSBarry Smith 
4437c5d6d63eSBarry Smith   PetscFunctionBegin;
44389b8102ccSHong Zhang   ierr = PetscLogEventBegin(MAT_Merge,inmat,0,0,0);CHKERRQ(ierr);
4439d6bb3c2dSHong Zhang   if (scall == MAT_INITIAL_MATRIX){
444090431a8fSHong Zhang     ierr = MatCreateMPIAIJConcatenateSeqAIJSymbolic(comm,inmat,n,outmat);CHKERRQ(ierr);
44410e36024fSHong Zhang   }
444290431a8fSHong Zhang   ierr = MatCreateMPIAIJConcatenateSeqAIJNumeric(comm,inmat,n,*outmat);CHKERRQ(ierr);
44439b8102ccSHong Zhang   ierr = PetscLogEventEnd(MAT_Merge,inmat,0,0,0);CHKERRQ(ierr);
4444c5d6d63eSBarry Smith   PetscFunctionReturn(0);
4445c5d6d63eSBarry Smith }
4446c5d6d63eSBarry Smith 
4447c5d6d63eSBarry Smith #undef __FUNCT__
4448c5d6d63eSBarry Smith #define __FUNCT__ "MatFileSplit"
4449dfbe8321SBarry Smith PetscErrorCode MatFileSplit(Mat A,char *outfile)
4450c5d6d63eSBarry Smith {
4451dfbe8321SBarry Smith   PetscErrorCode    ierr;
445232dcc486SBarry Smith   PetscMPIInt       rank;
4453b1d57f15SBarry Smith   PetscInt          m,N,i,rstart,nnz;
4454de4209c5SBarry Smith   size_t            len;
4455b1d57f15SBarry Smith   const PetscInt    *indx;
4456c5d6d63eSBarry Smith   PetscViewer       out;
4457c5d6d63eSBarry Smith   char              *name;
4458c5d6d63eSBarry Smith   Mat               B;
4459b3cc6726SBarry Smith   const PetscScalar *values;
4460c5d6d63eSBarry Smith 
4461c5d6d63eSBarry Smith   PetscFunctionBegin;
4462c5d6d63eSBarry Smith   ierr = MatGetLocalSize(A,&m,0);CHKERRQ(ierr);
4463c5d6d63eSBarry Smith   ierr = MatGetSize(A,0,&N);CHKERRQ(ierr);
4464f204ca49SKris Buschelman   /* Should this be the type of the diagonal block of A? */
4465f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&B);CHKERRQ(ierr);
4466f69a0ea3SMatthew Knepley   ierr = MatSetSizes(B,m,N,m,N);CHKERRQ(ierr);
4467a2f3521dSMark F. Adams   ierr = MatSetBlockSizes(B,A->rmap->bs,A->cmap->bs);CHKERRQ(ierr);
4468f204ca49SKris Buschelman   ierr = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
4469f204ca49SKris Buschelman   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
4470c5d6d63eSBarry Smith   ierr = MatGetOwnershipRange(A,&rstart,0);CHKERRQ(ierr);
4471c5d6d63eSBarry Smith   for (i=0;i<m;i++) {
4472c5d6d63eSBarry Smith     ierr = MatGetRow(A,i+rstart,&nnz,&indx,&values);CHKERRQ(ierr);
4473c5d6d63eSBarry Smith     ierr = MatSetValues(B,1,&i,nnz,indx,values,INSERT_VALUES);CHKERRQ(ierr);
4474c5d6d63eSBarry Smith     ierr = MatRestoreRow(A,i+rstart,&nnz,&indx,&values);CHKERRQ(ierr);
4475c5d6d63eSBarry Smith   }
4476c5d6d63eSBarry Smith   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4477c5d6d63eSBarry Smith   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4478c5d6d63eSBarry Smith 
44797adad957SLisandro Dalcin   ierr = MPI_Comm_rank(((PetscObject)A)->comm,&rank);CHKERRQ(ierr);
4480c5d6d63eSBarry Smith   ierr = PetscStrlen(outfile,&len);CHKERRQ(ierr);
4481c5d6d63eSBarry Smith   ierr = PetscMalloc((len+5)*sizeof(char),&name);CHKERRQ(ierr);
4482c5d6d63eSBarry Smith   sprintf(name,"%s.%d",outfile,rank);
4483852598b0SBarry Smith   ierr = PetscViewerBinaryOpen(PETSC_COMM_SELF,name,FILE_MODE_APPEND,&out);CHKERRQ(ierr);
4484c5d6d63eSBarry Smith   ierr = PetscFree(name);
4485c5d6d63eSBarry Smith   ierr = MatView(B,out);CHKERRQ(ierr);
44866bf464f9SBarry Smith   ierr = PetscViewerDestroy(&out);CHKERRQ(ierr);
44876bf464f9SBarry Smith   ierr = MatDestroy(&B);CHKERRQ(ierr);
4488c5d6d63eSBarry Smith   PetscFunctionReturn(0);
4489c5d6d63eSBarry Smith }
4490e5f2cdd8SHong Zhang 
449109573ac7SBarry Smith extern PetscErrorCode MatDestroy_MPIAIJ(Mat);
449251a7d1a8SHong Zhang #undef __FUNCT__
449351a7d1a8SHong Zhang #define __FUNCT__ "MatDestroy_MPIAIJ_SeqsToMPI"
44947087cfbeSBarry Smith PetscErrorCode  MatDestroy_MPIAIJ_SeqsToMPI(Mat A)
449551a7d1a8SHong Zhang {
449651a7d1a8SHong Zhang   PetscErrorCode       ierr;
4497671beff6SHong Zhang   Mat_Merge_SeqsToMPI  *merge;
4498776b82aeSLisandro Dalcin   PetscContainer       container;
449951a7d1a8SHong Zhang 
450051a7d1a8SHong Zhang   PetscFunctionBegin;
4501671beff6SHong Zhang   ierr = PetscObjectQuery((PetscObject)A,"MatMergeSeqsToMPI",(PetscObject *)&container);CHKERRQ(ierr);
4502671beff6SHong Zhang   if (container) {
4503776b82aeSLisandro Dalcin     ierr = PetscContainerGetPointer(container,(void **)&merge);CHKERRQ(ierr);
450451a7d1a8SHong Zhang     ierr = PetscFree(merge->id_r);CHKERRQ(ierr);
45053e06a4e6SHong Zhang     ierr = PetscFree(merge->len_s);CHKERRQ(ierr);
45063e06a4e6SHong Zhang     ierr = PetscFree(merge->len_r);CHKERRQ(ierr);
450751a7d1a8SHong Zhang     ierr = PetscFree(merge->bi);CHKERRQ(ierr);
450851a7d1a8SHong Zhang     ierr = PetscFree(merge->bj);CHKERRQ(ierr);
4509533163c2SBarry Smith     ierr = PetscFree(merge->buf_ri[0]);CHKERRQ(ierr);
451002c68681SHong Zhang     ierr = PetscFree(merge->buf_ri);CHKERRQ(ierr);
4511533163c2SBarry Smith     ierr = PetscFree(merge->buf_rj[0]);CHKERRQ(ierr);
451202c68681SHong Zhang     ierr = PetscFree(merge->buf_rj);CHKERRQ(ierr);
451305b42c5fSBarry Smith     ierr = PetscFree(merge->coi);CHKERRQ(ierr);
451405b42c5fSBarry Smith     ierr = PetscFree(merge->coj);CHKERRQ(ierr);
451505b42c5fSBarry Smith     ierr = PetscFree(merge->owners_co);CHKERRQ(ierr);
45166bf464f9SBarry Smith     ierr = PetscLayoutDestroy(&merge->rowmap);CHKERRQ(ierr);
4517bf0cc555SLisandro Dalcin     ierr = PetscFree(merge);CHKERRQ(ierr);
4518671beff6SHong Zhang     ierr = PetscObjectCompose((PetscObject)A,"MatMergeSeqsToMPI",0);CHKERRQ(ierr);
4519671beff6SHong Zhang   }
452051a7d1a8SHong Zhang   ierr = MatDestroy_MPIAIJ(A);CHKERRQ(ierr);
452151a7d1a8SHong Zhang   PetscFunctionReturn(0);
452251a7d1a8SHong Zhang }
452351a7d1a8SHong Zhang 
4524c6db04a5SJed Brown #include <../src/mat/utils/freespace.h>
4525c6db04a5SJed Brown #include <petscbt.h>
45264ebed01fSBarry Smith 
4527e5f2cdd8SHong Zhang #undef __FUNCT__
452890431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJSumSeqAIJNumeric"
452990431a8fSHong Zhang PetscErrorCode  MatCreateMPIAIJSumSeqAIJNumeric(Mat seqmat,Mat mpimat)
453055d1abb9SHong Zhang {
453155d1abb9SHong Zhang   PetscErrorCode       ierr;
45327adad957SLisandro Dalcin   MPI_Comm             comm=((PetscObject)mpimat)->comm;
453355d1abb9SHong Zhang   Mat_SeqAIJ           *a=(Mat_SeqAIJ*)seqmat->data;
4534b1d57f15SBarry Smith   PetscMPIInt          size,rank,taga,*len_s;
4535d0f46423SBarry Smith   PetscInt             N=mpimat->cmap->N,i,j,*owners,*ai=a->i,*aj=a->j;
4536b1d57f15SBarry Smith   PetscInt             proc,m;
4537b1d57f15SBarry Smith   PetscInt             **buf_ri,**buf_rj;
4538b1d57f15SBarry Smith   PetscInt             k,anzi,*bj_i,*bi,*bj,arow,bnzi,nextaj;
4539b1d57f15SBarry Smith   PetscInt             nrows,**buf_ri_k,**nextrow,**nextai;
454055d1abb9SHong Zhang   MPI_Request          *s_waits,*r_waits;
454155d1abb9SHong Zhang   MPI_Status           *status;
4542a77337e4SBarry Smith   MatScalar            *aa=a->a;
4543dd6ea824SBarry Smith   MatScalar            **abuf_r,*ba_i;
454455d1abb9SHong Zhang   Mat_Merge_SeqsToMPI  *merge;
4545776b82aeSLisandro Dalcin   PetscContainer       container;
454655d1abb9SHong Zhang 
454755d1abb9SHong Zhang   PetscFunctionBegin;
45484ebed01fSBarry Smith   ierr = PetscLogEventBegin(MAT_Seqstompinum,seqmat,0,0,0);CHKERRQ(ierr);
45493c2c1871SHong Zhang 
455055d1abb9SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
455155d1abb9SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
455255d1abb9SHong Zhang 
455355d1abb9SHong Zhang   ierr = PetscObjectQuery((PetscObject)mpimat,"MatMergeSeqsToMPI",(PetscObject *)&container);CHKERRQ(ierr);
4554776b82aeSLisandro Dalcin   ierr  = PetscContainerGetPointer(container,(void **)&merge);CHKERRQ(ierr);
4555bf0cc555SLisandro Dalcin 
455655d1abb9SHong Zhang   bi     = merge->bi;
455755d1abb9SHong Zhang   bj     = merge->bj;
455855d1abb9SHong Zhang   buf_ri = merge->buf_ri;
455955d1abb9SHong Zhang   buf_rj = merge->buf_rj;
456055d1abb9SHong Zhang 
456155d1abb9SHong Zhang   ierr   = PetscMalloc(size*sizeof(MPI_Status),&status);CHKERRQ(ierr);
45627a2fc3feSBarry Smith   owners = merge->rowmap->range;
456355d1abb9SHong Zhang   len_s  = merge->len_s;
456455d1abb9SHong Zhang 
456555d1abb9SHong Zhang   /* send and recv matrix values */
456655d1abb9SHong Zhang   /*-----------------------------*/
4567357abbc8SBarry Smith   ierr = PetscObjectGetNewTag((PetscObject)mpimat,&taga);CHKERRQ(ierr);
456855d1abb9SHong Zhang   ierr = PetscPostIrecvScalar(comm,taga,merge->nrecv,merge->id_r,merge->len_r,&abuf_r,&r_waits);CHKERRQ(ierr);
456955d1abb9SHong Zhang 
457055d1abb9SHong Zhang   ierr = PetscMalloc((merge->nsend+1)*sizeof(MPI_Request),&s_waits);CHKERRQ(ierr);
457155d1abb9SHong Zhang   for (proc=0,k=0; proc<size; proc++){
457255d1abb9SHong Zhang     if (!len_s[proc]) continue;
457355d1abb9SHong Zhang     i = owners[proc];
457455d1abb9SHong Zhang     ierr = MPI_Isend(aa+ai[i],len_s[proc],MPIU_MATSCALAR,proc,taga,comm,s_waits+k);CHKERRQ(ierr);
457555d1abb9SHong Zhang     k++;
457655d1abb9SHong Zhang   }
457755d1abb9SHong Zhang 
45780c468ba9SBarry Smith   if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,r_waits,status);CHKERRQ(ierr);}
45790c468ba9SBarry Smith   if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,s_waits,status);CHKERRQ(ierr);}
458055d1abb9SHong Zhang   ierr = PetscFree(status);CHKERRQ(ierr);
458155d1abb9SHong Zhang 
458255d1abb9SHong Zhang   ierr = PetscFree(s_waits);CHKERRQ(ierr);
458355d1abb9SHong Zhang   ierr = PetscFree(r_waits);CHKERRQ(ierr);
458455d1abb9SHong Zhang 
458555d1abb9SHong Zhang   /* insert mat values of mpimat */
458655d1abb9SHong Zhang   /*----------------------------*/
4587a77337e4SBarry Smith   ierr = PetscMalloc(N*sizeof(PetscScalar),&ba_i);CHKERRQ(ierr);
45880572522cSBarry Smith   ierr = PetscMalloc3(merge->nrecv,PetscInt*,&buf_ri_k,merge->nrecv,PetscInt*,&nextrow,merge->nrecv,PetscInt*,&nextai);CHKERRQ(ierr);
458955d1abb9SHong Zhang 
459055d1abb9SHong Zhang   for (k=0; k<merge->nrecv; k++){
459155d1abb9SHong Zhang     buf_ri_k[k] = buf_ri[k]; /* beginning of k-th recved i-structure */
459255d1abb9SHong Zhang     nrows = *(buf_ri_k[k]);
459355d1abb9SHong Zhang     nextrow[k]  = buf_ri_k[k]+1;  /* next row number of k-th recved i-structure */
459455d1abb9SHong Zhang     nextai[k]   = buf_ri_k[k] + (nrows + 1);/* poins to the next i-structure of k-th recved i-structure  */
459555d1abb9SHong Zhang   }
459655d1abb9SHong Zhang 
459755d1abb9SHong Zhang   /* set values of ba */
45987a2fc3feSBarry Smith   m = merge->rowmap->n;
459955d1abb9SHong Zhang   for (i=0; i<m; i++) {
460055d1abb9SHong Zhang     arow = owners[rank] + i;
460155d1abb9SHong Zhang     bj_i = bj+bi[i];  /* col indices of the i-th row of mpimat */
460255d1abb9SHong Zhang     bnzi = bi[i+1] - bi[i];
4603a77337e4SBarry Smith     ierr = PetscMemzero(ba_i,bnzi*sizeof(PetscScalar));CHKERRQ(ierr);
460455d1abb9SHong Zhang 
460555d1abb9SHong Zhang     /* add local non-zero vals of this proc's seqmat into ba */
460655d1abb9SHong Zhang     anzi = ai[arow+1] - ai[arow];
460755d1abb9SHong Zhang     aj   = a->j + ai[arow];
460855d1abb9SHong Zhang     aa   = a->a + ai[arow];
460955d1abb9SHong Zhang     nextaj = 0;
461055d1abb9SHong Zhang     for (j=0; nextaj<anzi; j++){
461155d1abb9SHong Zhang       if (*(bj_i + j) == aj[nextaj]){ /* bcol == acol */
461255d1abb9SHong Zhang         ba_i[j] += aa[nextaj++];
461355d1abb9SHong Zhang       }
461455d1abb9SHong Zhang     }
461555d1abb9SHong Zhang 
461655d1abb9SHong Zhang     /* add received vals into ba */
461755d1abb9SHong Zhang     for (k=0; k<merge->nrecv; k++){ /* k-th received message */
461855d1abb9SHong Zhang       /* i-th row */
461955d1abb9SHong Zhang       if (i == *nextrow[k]) {
462055d1abb9SHong Zhang         anzi = *(nextai[k]+1) - *nextai[k];
462155d1abb9SHong Zhang         aj   = buf_rj[k] + *(nextai[k]);
462255d1abb9SHong Zhang         aa   = abuf_r[k] + *(nextai[k]);
462355d1abb9SHong Zhang         nextaj = 0;
462455d1abb9SHong Zhang         for (j=0; nextaj<anzi; j++){
462555d1abb9SHong Zhang           if (*(bj_i + j) == aj[nextaj]){ /* bcol == acol */
462655d1abb9SHong Zhang             ba_i[j] += aa[nextaj++];
462755d1abb9SHong Zhang           }
462855d1abb9SHong Zhang         }
462955d1abb9SHong Zhang         nextrow[k]++; nextai[k]++;
463055d1abb9SHong Zhang       }
463155d1abb9SHong Zhang     }
463255d1abb9SHong Zhang     ierr = MatSetValues(mpimat,1,&arow,bnzi,bj_i,ba_i,INSERT_VALUES);CHKERRQ(ierr);
463355d1abb9SHong Zhang   }
463455d1abb9SHong Zhang   ierr = MatAssemblyBegin(mpimat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
463555d1abb9SHong Zhang   ierr = MatAssemblyEnd(mpimat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
463655d1abb9SHong Zhang 
4637533163c2SBarry Smith   ierr = PetscFree(abuf_r[0]);CHKERRQ(ierr);
463855d1abb9SHong Zhang   ierr = PetscFree(abuf_r);CHKERRQ(ierr);
463955d1abb9SHong Zhang   ierr = PetscFree(ba_i);CHKERRQ(ierr);
46401d79065fSBarry Smith   ierr = PetscFree3(buf_ri_k,nextrow,nextai);CHKERRQ(ierr);
46414ebed01fSBarry Smith   ierr = PetscLogEventEnd(MAT_Seqstompinum,seqmat,0,0,0);CHKERRQ(ierr);
464255d1abb9SHong Zhang   PetscFunctionReturn(0);
464355d1abb9SHong Zhang }
464438f152feSBarry Smith 
46456bc0bbbfSBarry Smith extern PetscErrorCode  MatDestroy_MPIAIJ_SeqsToMPI(Mat);
46466bc0bbbfSBarry Smith 
464738f152feSBarry Smith #undef __FUNCT__
464890431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJSumSeqAIJSymbolic"
464990431a8fSHong Zhang PetscErrorCode  MatCreateMPIAIJSumSeqAIJSymbolic(MPI_Comm comm,Mat seqmat,PetscInt m,PetscInt n,Mat *mpimat)
4650e5f2cdd8SHong Zhang {
4651f08fae4eSHong Zhang   PetscErrorCode       ierr;
465255a3bba9SHong Zhang   Mat                  B_mpi;
4653c2234fe3SHong Zhang   Mat_SeqAIJ           *a=(Mat_SeqAIJ*)seqmat->data;
4654b1d57f15SBarry Smith   PetscMPIInt          size,rank,tagi,tagj,*len_s,*len_si,*len_ri;
4655b1d57f15SBarry Smith   PetscInt             **buf_rj,**buf_ri,**buf_ri_k;
4656d0f46423SBarry Smith   PetscInt             M=seqmat->rmap->n,N=seqmat->cmap->n,i,*owners,*ai=a->i,*aj=a->j;
4657a2f3521dSMark F. Adams   PetscInt             len,proc,*dnz,*onz,bs,cbs;
4658b1d57f15SBarry Smith   PetscInt             k,anzi,*bi,*bj,*lnk,nlnk,arow,bnzi,nspacedouble=0;
4659b1d57f15SBarry Smith   PetscInt             nrows,*buf_s,*buf_si,*buf_si_i,**nextrow,**nextai;
466055d1abb9SHong Zhang   MPI_Request          *si_waits,*sj_waits,*ri_waits,*rj_waits;
466158cb9c82SHong Zhang   MPI_Status           *status;
4662a1a86e44SBarry Smith   PetscFreeSpaceList   free_space=PETSC_NULL,current_space=PETSC_NULL;
4663be0fcf8dSHong Zhang   PetscBT              lnkbt;
466451a7d1a8SHong Zhang   Mat_Merge_SeqsToMPI  *merge;
4665776b82aeSLisandro Dalcin   PetscContainer       container;
466602c68681SHong Zhang 
4667e5f2cdd8SHong Zhang   PetscFunctionBegin;
46684ebed01fSBarry Smith   ierr = PetscLogEventBegin(MAT_Seqstompisym,seqmat,0,0,0);CHKERRQ(ierr);
46693c2c1871SHong Zhang 
467038f152feSBarry Smith   /* make sure it is a PETSc comm */
467138f152feSBarry Smith   ierr = PetscCommDuplicate(comm,&comm,PETSC_NULL);CHKERRQ(ierr);
4672e5f2cdd8SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
4673e5f2cdd8SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
467455d1abb9SHong Zhang 
467551a7d1a8SHong Zhang   ierr = PetscNew(Mat_Merge_SeqsToMPI,&merge);CHKERRQ(ierr);
4676c2234fe3SHong Zhang   ierr = PetscMalloc(size*sizeof(MPI_Status),&status);CHKERRQ(ierr);
4677e5f2cdd8SHong Zhang 
46786abd8857SHong Zhang   /* determine row ownership */
4679f08fae4eSHong Zhang   /*---------------------------------------------------------*/
468026283091SBarry Smith   ierr = PetscLayoutCreate(comm,&merge->rowmap);CHKERRQ(ierr);
468126283091SBarry Smith   ierr = PetscLayoutSetLocalSize(merge->rowmap,m);CHKERRQ(ierr);
468226283091SBarry Smith   ierr = PetscLayoutSetSize(merge->rowmap,M);CHKERRQ(ierr);
468326283091SBarry Smith   ierr = PetscLayoutSetBlockSize(merge->rowmap,1);CHKERRQ(ierr);
468426283091SBarry Smith   ierr = PetscLayoutSetUp(merge->rowmap);CHKERRQ(ierr);
4685b1d57f15SBarry Smith   ierr = PetscMalloc(size*sizeof(PetscMPIInt),&len_si);CHKERRQ(ierr);
4686b1d57f15SBarry Smith   ierr = PetscMalloc(size*sizeof(PetscMPIInt),&merge->len_s);CHKERRQ(ierr);
468755d1abb9SHong Zhang 
46887a2fc3feSBarry Smith   m      = merge->rowmap->n;
46897a2fc3feSBarry Smith   M      = merge->rowmap->N;
46907a2fc3feSBarry Smith   owners = merge->rowmap->range;
46916abd8857SHong Zhang 
46926abd8857SHong Zhang   /* determine the number of messages to send, their lengths */
46936abd8857SHong Zhang   /*---------------------------------------------------------*/
46943e06a4e6SHong Zhang   len_s  = merge->len_s;
469551a7d1a8SHong Zhang 
46962257cef7SHong Zhang   len = 0;  /* length of buf_si[] */
4697c2234fe3SHong Zhang   merge->nsend = 0;
4698409913e3SHong Zhang   for (proc=0; proc<size; proc++){
46992257cef7SHong Zhang     len_si[proc] = 0;
47003e06a4e6SHong Zhang     if (proc == rank){
47016abd8857SHong Zhang       len_s[proc] = 0;
47023e06a4e6SHong Zhang     } else {
470302c68681SHong Zhang       len_si[proc] = owners[proc+1] - owners[proc] + 1;
47043e06a4e6SHong Zhang       len_s[proc] = ai[owners[proc+1]] - ai[owners[proc]]; /* num of rows to be sent to [proc] */
47053e06a4e6SHong Zhang     }
47063e06a4e6SHong Zhang     if (len_s[proc]) {
4707c2234fe3SHong Zhang       merge->nsend++;
47082257cef7SHong Zhang       nrows = 0;
47092257cef7SHong Zhang       for (i=owners[proc]; i<owners[proc+1]; i++){
47102257cef7SHong Zhang         if (ai[i+1] > ai[i]) nrows++;
47112257cef7SHong Zhang       }
47122257cef7SHong Zhang       len_si[proc] = 2*(nrows+1);
47132257cef7SHong Zhang       len += len_si[proc];
4714409913e3SHong Zhang     }
471558cb9c82SHong Zhang   }
4716409913e3SHong Zhang 
47172257cef7SHong Zhang   /* determine the number and length of messages to receive for ij-structure */
47182257cef7SHong Zhang   /*-------------------------------------------------------------------------*/
471951a7d1a8SHong Zhang   ierr = PetscGatherNumberOfMessages(comm,PETSC_NULL,len_s,&merge->nrecv);CHKERRQ(ierr);
472055d1abb9SHong Zhang   ierr = PetscGatherMessageLengths2(comm,merge->nsend,merge->nrecv,len_s,len_si,&merge->id_r,&merge->len_r,&len_ri);CHKERRQ(ierr);
4721671beff6SHong Zhang 
47223e06a4e6SHong Zhang   /* post the Irecv of j-structure */
47233e06a4e6SHong Zhang   /*-------------------------------*/
47242c72b5baSSatish Balay   ierr = PetscCommGetNewTag(comm,&tagj);CHKERRQ(ierr);
47253e06a4e6SHong Zhang   ierr = PetscPostIrecvInt(comm,tagj,merge->nrecv,merge->id_r,merge->len_r,&buf_rj,&rj_waits);CHKERRQ(ierr);
472602c68681SHong Zhang 
47273e06a4e6SHong Zhang   /* post the Isend of j-structure */
4728affca5deSHong Zhang   /*--------------------------------*/
47291d79065fSBarry Smith   ierr = PetscMalloc2(merge->nsend,MPI_Request,&si_waits,merge->nsend,MPI_Request,&sj_waits);CHKERRQ(ierr);
47303e06a4e6SHong Zhang 
47312257cef7SHong Zhang   for (proc=0, k=0; proc<size; proc++){
4732409913e3SHong Zhang     if (!len_s[proc]) continue;
473302c68681SHong Zhang     i = owners[proc];
4734b1d57f15SBarry Smith     ierr = MPI_Isend(aj+ai[i],len_s[proc],MPIU_INT,proc,tagj,comm,sj_waits+k);CHKERRQ(ierr);
473551a7d1a8SHong Zhang     k++;
473651a7d1a8SHong Zhang   }
473751a7d1a8SHong Zhang 
47383e06a4e6SHong Zhang   /* receives and sends of j-structure are complete */
47393e06a4e6SHong Zhang   /*------------------------------------------------*/
47400c468ba9SBarry Smith   if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,rj_waits,status);CHKERRQ(ierr);}
47410c468ba9SBarry Smith   if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,sj_waits,status);CHKERRQ(ierr);}
474202c68681SHong Zhang 
474302c68681SHong Zhang   /* send and recv i-structure */
474402c68681SHong Zhang   /*---------------------------*/
47452c72b5baSSatish Balay   ierr = PetscCommGetNewTag(comm,&tagi);CHKERRQ(ierr);
474602c68681SHong Zhang   ierr = PetscPostIrecvInt(comm,tagi,merge->nrecv,merge->id_r,len_ri,&buf_ri,&ri_waits);CHKERRQ(ierr);
474702c68681SHong Zhang 
4748b1d57f15SBarry Smith   ierr = PetscMalloc((len+1)*sizeof(PetscInt),&buf_s);CHKERRQ(ierr);
47493e06a4e6SHong Zhang   buf_si = buf_s;  /* points to the beginning of k-th msg to be sent */
47502257cef7SHong Zhang   for (proc=0,k=0; proc<size; proc++){
475102c68681SHong Zhang     if (!len_s[proc]) continue;
47523e06a4e6SHong Zhang     /* form outgoing message for i-structure:
47533e06a4e6SHong Zhang          buf_si[0]:                 nrows to be sent
47543e06a4e6SHong Zhang                [1:nrows]:           row index (global)
47553e06a4e6SHong Zhang                [nrows+1:2*nrows+1]: i-structure index
47563e06a4e6SHong Zhang     */
47573e06a4e6SHong Zhang     /*-------------------------------------------*/
47582257cef7SHong Zhang     nrows = len_si[proc]/2 - 1;
47593e06a4e6SHong Zhang     buf_si_i    = buf_si + nrows+1;
47603e06a4e6SHong Zhang     buf_si[0]   = nrows;
47613e06a4e6SHong Zhang     buf_si_i[0] = 0;
47623e06a4e6SHong Zhang     nrows = 0;
47633e06a4e6SHong Zhang     for (i=owners[proc]; i<owners[proc+1]; i++){
47643e06a4e6SHong Zhang       anzi = ai[i+1] - ai[i];
47653e06a4e6SHong Zhang       if (anzi) {
47663e06a4e6SHong Zhang         buf_si_i[nrows+1] = buf_si_i[nrows] + anzi; /* i-structure */
47673e06a4e6SHong Zhang         buf_si[nrows+1] = i-owners[proc]; /* local row index */
47683e06a4e6SHong Zhang         nrows++;
47693e06a4e6SHong Zhang       }
47703e06a4e6SHong Zhang     }
4771b1d57f15SBarry Smith     ierr = MPI_Isend(buf_si,len_si[proc],MPIU_INT,proc,tagi,comm,si_waits+k);CHKERRQ(ierr);
477202c68681SHong Zhang     k++;
47732257cef7SHong Zhang     buf_si += len_si[proc];
477402c68681SHong Zhang   }
47752257cef7SHong Zhang 
47760c468ba9SBarry Smith   if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,ri_waits,status);CHKERRQ(ierr);}
47770c468ba9SBarry Smith   if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,si_waits,status);CHKERRQ(ierr);}
477802c68681SHong Zhang 
4779ae15b995SBarry Smith   ierr = PetscInfo2(seqmat,"nsend: %D, nrecv: %D\n",merge->nsend,merge->nrecv);CHKERRQ(ierr);
47803e06a4e6SHong Zhang   for (i=0; i<merge->nrecv; i++){
4781ae15b995SBarry Smith     ierr = PetscInfo3(seqmat,"recv len_ri=%D, len_rj=%D from [%D]\n",len_ri[i],merge->len_r[i],merge->id_r[i]);CHKERRQ(ierr);
47823e06a4e6SHong Zhang   }
47833e06a4e6SHong Zhang 
47843e06a4e6SHong Zhang   ierr = PetscFree(len_si);CHKERRQ(ierr);
478502c68681SHong Zhang   ierr = PetscFree(len_ri);CHKERRQ(ierr);
478602c68681SHong Zhang   ierr = PetscFree(rj_waits);CHKERRQ(ierr);
47871d79065fSBarry Smith   ierr = PetscFree2(si_waits,sj_waits);CHKERRQ(ierr);
47882257cef7SHong Zhang   ierr = PetscFree(ri_waits);CHKERRQ(ierr);
47893e06a4e6SHong Zhang   ierr = PetscFree(buf_s);CHKERRQ(ierr);
4790bcc1bcd5SHong Zhang   ierr = PetscFree(status);CHKERRQ(ierr);
479158cb9c82SHong Zhang 
4792bcc1bcd5SHong Zhang   /* compute a local seq matrix in each processor */
4793bcc1bcd5SHong Zhang   /*----------------------------------------------*/
479458cb9c82SHong Zhang   /* allocate bi array and free space for accumulating nonzero column info */
4795b1d57f15SBarry Smith   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&bi);CHKERRQ(ierr);
479658cb9c82SHong Zhang   bi[0] = 0;
479758cb9c82SHong Zhang 
4798be0fcf8dSHong Zhang   /* create and initialize a linked list */
4799be0fcf8dSHong Zhang   nlnk = N+1;
4800be0fcf8dSHong Zhang   ierr = PetscLLCreate(N,N,nlnk,lnk,lnkbt);CHKERRQ(ierr);
480158cb9c82SHong Zhang 
4802bcc1bcd5SHong Zhang   /* initial FreeSpace size is 2*(num of local nnz(seqmat)) */
480358cb9c82SHong Zhang   len = 0;
4804bcc1bcd5SHong Zhang   len  = ai[owners[rank+1]] - ai[owners[rank]];
4805a1a86e44SBarry Smith   ierr = PetscFreeSpaceGet((PetscInt)(2*len+1),&free_space);CHKERRQ(ierr);
480658cb9c82SHong Zhang   current_space = free_space;
480758cb9c82SHong Zhang 
4808bcc1bcd5SHong Zhang   /* determine symbolic info for each local row */
48090572522cSBarry Smith   ierr = PetscMalloc3(merge->nrecv,PetscInt*,&buf_ri_k,merge->nrecv,PetscInt*,&nextrow,merge->nrecv,PetscInt*,&nextai);CHKERRQ(ierr);
48101d79065fSBarry Smith 
48113e06a4e6SHong Zhang   for (k=0; k<merge->nrecv; k++){
48122257cef7SHong Zhang     buf_ri_k[k] = buf_ri[k]; /* beginning of k-th recved i-structure */
48133e06a4e6SHong Zhang     nrows = *buf_ri_k[k];
48143e06a4e6SHong Zhang     nextrow[k]  = buf_ri_k[k] + 1;  /* next row number of k-th recved i-structure */
48152257cef7SHong Zhang     nextai[k]   = buf_ri_k[k] + (nrows + 1);/* poins to the next i-structure of k-th recved i-structure  */
48163e06a4e6SHong Zhang   }
48172257cef7SHong Zhang 
4818bcc1bcd5SHong Zhang   ierr = MatPreallocateInitialize(comm,m,n,dnz,onz);CHKERRQ(ierr);
4819bcc1bcd5SHong Zhang   len = 0;
482058cb9c82SHong Zhang   for (i=0;i<m;i++) {
482158cb9c82SHong Zhang     bnzi   = 0;
482258cb9c82SHong Zhang     /* add local non-zero cols of this proc's seqmat into lnk */
482358cb9c82SHong Zhang     arow   = owners[rank] + i;
482458cb9c82SHong Zhang     anzi   = ai[arow+1] - ai[arow];
482558cb9c82SHong Zhang     aj     = a->j + ai[arow];
4826dadf0e6bSHong Zhang     ierr = PetscLLAddSorted(anzi,aj,N,nlnk,lnk,lnkbt);CHKERRQ(ierr);
482758cb9c82SHong Zhang     bnzi += nlnk;
482858cb9c82SHong Zhang     /* add received col data into lnk */
482951a7d1a8SHong Zhang     for (k=0; k<merge->nrecv; k++){ /* k-th received message */
483055d1abb9SHong Zhang       if (i == *nextrow[k]) { /* i-th row */
48313e06a4e6SHong Zhang         anzi = *(nextai[k]+1) - *nextai[k];
48323e06a4e6SHong Zhang         aj   = buf_rj[k] + *nextai[k];
4833dadf0e6bSHong Zhang         ierr = PetscLLAddSorted(anzi,aj,N,nlnk,lnk,lnkbt);CHKERRQ(ierr);
48343e06a4e6SHong Zhang         bnzi += nlnk;
48353e06a4e6SHong Zhang         nextrow[k]++; nextai[k]++;
48363e06a4e6SHong Zhang       }
483758cb9c82SHong Zhang     }
4838bcc1bcd5SHong Zhang     if (len < bnzi) len = bnzi;  /* =max(bnzi) */
483958cb9c82SHong Zhang 
484058cb9c82SHong Zhang     /* if free space is not available, make more free space */
484158cb9c82SHong Zhang     if (current_space->local_remaining<bnzi) {
48424238b7adSHong Zhang       ierr = PetscFreeSpaceGet(bnzi+current_space->total_array_size,&current_space);CHKERRQ(ierr);
484358cb9c82SHong Zhang       nspacedouble++;
484458cb9c82SHong Zhang     }
484558cb9c82SHong Zhang     /* copy data into free space, then initialize lnk */
4846be0fcf8dSHong Zhang     ierr = PetscLLClean(N,N,bnzi,lnk,current_space->array,lnkbt);CHKERRQ(ierr);
4847bcc1bcd5SHong Zhang     ierr = MatPreallocateSet(i+owners[rank],bnzi,current_space->array,dnz,onz);CHKERRQ(ierr);
4848bcc1bcd5SHong Zhang 
484958cb9c82SHong Zhang     current_space->array           += bnzi;
485058cb9c82SHong Zhang     current_space->local_used      += bnzi;
485158cb9c82SHong Zhang     current_space->local_remaining -= bnzi;
485258cb9c82SHong Zhang 
485358cb9c82SHong Zhang     bi[i+1] = bi[i] + bnzi;
485458cb9c82SHong Zhang   }
4855bcc1bcd5SHong Zhang 
48561d79065fSBarry Smith   ierr = PetscFree3(buf_ri_k,nextrow,nextai);CHKERRQ(ierr);
4857bcc1bcd5SHong Zhang 
4858b1d57f15SBarry Smith   ierr = PetscMalloc((bi[m]+1)*sizeof(PetscInt),&bj);CHKERRQ(ierr);
4859a1a86e44SBarry Smith   ierr = PetscFreeSpaceContiguous(&free_space,bj);CHKERRQ(ierr);
4860be0fcf8dSHong Zhang   ierr = PetscLLDestroy(lnk,lnkbt);CHKERRQ(ierr);
4861409913e3SHong Zhang 
4862bcc1bcd5SHong Zhang   /* create symbolic parallel matrix B_mpi */
4863bcc1bcd5SHong Zhang   /*---------------------------------------*/
4864a2f3521dSMark F. Adams     ierr = MatGetBlockSizes(seqmat,&bs,&cbs);CHKERRQ(ierr);
4865f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,&B_mpi);CHKERRQ(ierr);
486654b84b50SHong Zhang   if (n==PETSC_DECIDE) {
4867f69a0ea3SMatthew Knepley     ierr = MatSetSizes(B_mpi,m,n,PETSC_DETERMINE,N);CHKERRQ(ierr);
486854b84b50SHong Zhang   } else {
4869f69a0ea3SMatthew Knepley     ierr = MatSetSizes(B_mpi,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
487054b84b50SHong Zhang   }
4871a2f3521dSMark F. Adams   ierr = MatSetBlockSizes(B_mpi,bs,cbs); CHKERRQ(ierr);
4872bcc1bcd5SHong Zhang   ierr = MatSetType(B_mpi,MATMPIAIJ);CHKERRQ(ierr);
4873bcc1bcd5SHong Zhang   ierr = MatMPIAIJSetPreallocation(B_mpi,0,dnz,0,onz);CHKERRQ(ierr);
4874bcc1bcd5SHong Zhang   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
48757e63b356SHong Zhang   ierr = MatSetOption(B_mpi,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
487658cb9c82SHong Zhang 
487790431a8fSHong Zhang   /* B_mpi is not ready for use - assembly will be done by MatCreateMPIAIJSumSeqAIJNumeric() */
48786abd8857SHong Zhang   B_mpi->assembled     = PETSC_FALSE;
4879affca5deSHong Zhang   B_mpi->ops->destroy  = MatDestroy_MPIAIJ_SeqsToMPI;
4880affca5deSHong Zhang   merge->bi            = bi;
4881affca5deSHong Zhang   merge->bj            = bj;
488202c68681SHong Zhang   merge->buf_ri        = buf_ri;
488302c68681SHong Zhang   merge->buf_rj        = buf_rj;
4884de0260b3SHong Zhang   merge->coi           = PETSC_NULL;
4885de0260b3SHong Zhang   merge->coj           = PETSC_NULL;
4886de0260b3SHong Zhang   merge->owners_co     = PETSC_NULL;
4887affca5deSHong Zhang 
4888bf0cc555SLisandro Dalcin   ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
4889bf0cc555SLisandro Dalcin 
4890affca5deSHong Zhang   /* attach the supporting struct to B_mpi for reuse */
4891776b82aeSLisandro Dalcin   ierr = PetscContainerCreate(PETSC_COMM_SELF,&container);CHKERRQ(ierr);
4892776b82aeSLisandro Dalcin   ierr = PetscContainerSetPointer(container,merge);CHKERRQ(ierr);
4893affca5deSHong Zhang   ierr = PetscObjectCompose((PetscObject)B_mpi,"MatMergeSeqsToMPI",(PetscObject)container);CHKERRQ(ierr);
4894bf0cc555SLisandro Dalcin   ierr = PetscContainerDestroy(&container);CHKERRQ(ierr);
4895affca5deSHong Zhang   *mpimat = B_mpi;
489638f152feSBarry Smith 
48974ebed01fSBarry Smith   ierr = PetscLogEventEnd(MAT_Seqstompisym,seqmat,0,0,0);CHKERRQ(ierr);
4898e5f2cdd8SHong Zhang   PetscFunctionReturn(0);
4899e5f2cdd8SHong Zhang }
490025616d81SHong Zhang 
490138f152feSBarry Smith #undef __FUNCT__
490290431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJSumSeqAIJ"
4903d4036a1aSHong Zhang /*@C
490490431a8fSHong Zhang       MatCreateMPIAIJSumSeqAIJ - Creates a MPIAIJ matrix by adding sequential
4905d4036a1aSHong Zhang                  matrices from each processor
4906d4036a1aSHong Zhang 
4907d4036a1aSHong Zhang     Collective on MPI_Comm
4908d4036a1aSHong Zhang 
4909d4036a1aSHong Zhang    Input Parameters:
4910d4036a1aSHong Zhang +    comm - the communicators the parallel matrix will live on
4911d4036a1aSHong Zhang .    seqmat - the input sequential matrices
4912d4036a1aSHong Zhang .    m - number of local rows (or PETSC_DECIDE)
4913d4036a1aSHong Zhang .    n - number of local columns (or PETSC_DECIDE)
4914d4036a1aSHong Zhang -    scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
4915d4036a1aSHong Zhang 
4916d4036a1aSHong Zhang    Output Parameter:
4917d4036a1aSHong Zhang .    mpimat - the parallel matrix generated
4918d4036a1aSHong Zhang 
4919d4036a1aSHong Zhang     Level: advanced
4920d4036a1aSHong Zhang 
4921d4036a1aSHong Zhang    Notes:
4922d4036a1aSHong Zhang      The dimensions of the sequential matrix in each processor MUST be the same.
4923d4036a1aSHong Zhang      The input seqmat is included into the container "Mat_Merge_SeqsToMPI", and will be
4924d4036a1aSHong Zhang      destroyed when mpimat is destroyed. Call PetscObjectQuery() to access seqmat.
4925d4036a1aSHong Zhang @*/
492690431a8fSHong Zhang PetscErrorCode  MatCreateMPIAIJSumSeqAIJ(MPI_Comm comm,Mat seqmat,PetscInt m,PetscInt n,MatReuse scall,Mat *mpimat)
492755d1abb9SHong Zhang {
492855d1abb9SHong Zhang   PetscErrorCode   ierr;
49297e63b356SHong Zhang   PetscMPIInt     size;
493055d1abb9SHong Zhang 
493155d1abb9SHong Zhang   PetscFunctionBegin;
49327e63b356SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
49337e63b356SHong Zhang   if (size == 1){
49347e63b356SHong Zhang      ierr = PetscLogEventBegin(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr);
49357e63b356SHong Zhang      if (scall == MAT_INITIAL_MATRIX){
49367e63b356SHong Zhang        ierr = MatDuplicate(seqmat,MAT_COPY_VALUES,mpimat);CHKERRQ(ierr);
49377e63b356SHong Zhang      } else {
49387e63b356SHong Zhang        ierr = MatCopy(seqmat,*mpimat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
49397e63b356SHong Zhang      }
49407e63b356SHong Zhang      ierr = PetscLogEventEnd(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr);
49417e63b356SHong Zhang      PetscFunctionReturn(0);
49427e63b356SHong Zhang   }
49434ebed01fSBarry Smith   ierr = PetscLogEventBegin(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr);
494455d1abb9SHong Zhang   if (scall == MAT_INITIAL_MATRIX){
494590431a8fSHong Zhang     ierr = MatCreateMPIAIJSumSeqAIJSymbolic(comm,seqmat,m,n,mpimat);CHKERRQ(ierr);
494655d1abb9SHong Zhang   }
494790431a8fSHong Zhang   ierr = MatCreateMPIAIJSumSeqAIJNumeric(seqmat,*mpimat);CHKERRQ(ierr);
49484ebed01fSBarry Smith   ierr = PetscLogEventEnd(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr);
494955d1abb9SHong Zhang   PetscFunctionReturn(0);
495055d1abb9SHong Zhang }
49514ebed01fSBarry Smith 
495225616d81SHong Zhang #undef __FUNCT__
49534a2b5492SBarry Smith #define __FUNCT__ "MatMPIAIJGetLocalMat"
4954bc08b0f1SBarry Smith /*@
49554a2b5492SBarry Smith      MatMPIAIJGetLocalMat - Creates a SeqAIJ from a MPIAIJ matrix by taking all its local rows and putting them into a sequential vector with
49568661ff28SBarry Smith           mlocal rows and n columns. Where mlocal is the row count obtained with MatGetLocalSize() and n is the global column count obtained
49578661ff28SBarry Smith           with MatGetSize()
495825616d81SHong Zhang 
495932fba14fSHong Zhang     Not Collective
496025616d81SHong Zhang 
496125616d81SHong Zhang    Input Parameters:
496225616d81SHong Zhang +    A - the matrix
496325616d81SHong Zhang .    scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
496425616d81SHong Zhang 
496525616d81SHong Zhang    Output Parameter:
496625616d81SHong Zhang .    A_loc - the local sequential matrix generated
496725616d81SHong Zhang 
496825616d81SHong Zhang     Level: developer
496925616d81SHong Zhang 
4970ba264940SBarry Smith .seealso: MatGetOwnerShipRange(), MatMPIAIJGetLocalMatCondensed()
49718661ff28SBarry Smith 
497225616d81SHong Zhang @*/
49734a2b5492SBarry Smith PetscErrorCode  MatMPIAIJGetLocalMat(Mat A,MatReuse scall,Mat *A_loc)
497425616d81SHong Zhang {
497525616d81SHong Zhang   PetscErrorCode  ierr;
497601b7ae99SHong Zhang   Mat_MPIAIJ      *mpimat=(Mat_MPIAIJ*)A->data;
497701b7ae99SHong Zhang   Mat_SeqAIJ      *mat,*a=(Mat_SeqAIJ*)(mpimat->A)->data,*b=(Mat_SeqAIJ*)(mpimat->B)->data;
497801b7ae99SHong Zhang   PetscInt        *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*cmap=mpimat->garray;
4979a77337e4SBarry Smith   MatScalar       *aa=a->a,*ba=b->a,*cam;
4980a77337e4SBarry Smith   PetscScalar     *ca;
4981d0f46423SBarry Smith   PetscInt        am=A->rmap->n,i,j,k,cstart=A->cmap->rstart;
49825a7d977cSHong Zhang   PetscInt        *ci,*cj,col,ncols_d,ncols_o,jo;
49838661ff28SBarry Smith   PetscBool       match;
498425616d81SHong Zhang 
498525616d81SHong Zhang   PetscFunctionBegin;
4986251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&match);CHKERRQ(ierr);
49878661ff28SBarry Smith   if (!match) SETERRQ(((PetscObject)A)->comm, PETSC_ERR_SUP,"Requires MPIAIJ matrix as input");
49884ebed01fSBarry Smith   ierr = PetscLogEventBegin(MAT_Getlocalmat,A,0,0,0);CHKERRQ(ierr);
498901b7ae99SHong Zhang   if (scall == MAT_INITIAL_MATRIX){
4990dea91ad1SHong Zhang     ierr = PetscMalloc((1+am)*sizeof(PetscInt),&ci);CHKERRQ(ierr);
4991dea91ad1SHong Zhang     ci[0] = 0;
499201b7ae99SHong Zhang     for (i=0; i<am; i++){
4993dea91ad1SHong Zhang       ci[i+1] = ci[i] + (ai[i+1] - ai[i]) + (bi[i+1] - bi[i]);
499401b7ae99SHong Zhang     }
4995dea91ad1SHong Zhang     ierr = PetscMalloc((1+ci[am])*sizeof(PetscInt),&cj);CHKERRQ(ierr);
4996dea91ad1SHong Zhang     ierr = PetscMalloc((1+ci[am])*sizeof(PetscScalar),&ca);CHKERRQ(ierr);
4997dea91ad1SHong Zhang     k = 0;
499801b7ae99SHong Zhang     for (i=0; i<am; i++) {
49995a7d977cSHong Zhang       ncols_o = bi[i+1] - bi[i];
50005a7d977cSHong Zhang       ncols_d = ai[i+1] - ai[i];
500101b7ae99SHong Zhang       /* off-diagonal portion of A */
50025a7d977cSHong Zhang       for (jo=0; jo<ncols_o; jo++) {
50035a7d977cSHong Zhang         col = cmap[*bj];
50045a7d977cSHong Zhang         if (col >= cstart) break;
50055a7d977cSHong Zhang         cj[k]   = col; bj++;
50065a7d977cSHong Zhang         ca[k++] = *ba++;
50075a7d977cSHong Zhang       }
50085a7d977cSHong Zhang       /* diagonal portion of A */
50095a7d977cSHong Zhang       for (j=0; j<ncols_d; j++) {
50105a7d977cSHong Zhang         cj[k]   = cstart + *aj++;
50115a7d977cSHong Zhang         ca[k++] = *aa++;
50125a7d977cSHong Zhang       }
50135a7d977cSHong Zhang       /* off-diagonal portion of A */
50145a7d977cSHong Zhang       for (j=jo; j<ncols_o; j++) {
50155a7d977cSHong Zhang         cj[k]   = cmap[*bj++];
50165a7d977cSHong Zhang         ca[k++] = *ba++;
50175a7d977cSHong Zhang       }
501825616d81SHong Zhang     }
5019dea91ad1SHong Zhang     /* put together the new matrix */
5020d0f46423SBarry Smith     ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,am,A->cmap->N,ci,cj,ca,A_loc);CHKERRQ(ierr);
5021dea91ad1SHong Zhang     /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */
5022dea91ad1SHong Zhang     /* Since these are PETSc arrays, change flags to free them as necessary. */
5023dea91ad1SHong Zhang     mat          = (Mat_SeqAIJ*)(*A_loc)->data;
5024e6b907acSBarry Smith     mat->free_a  = PETSC_TRUE;
5025e6b907acSBarry Smith     mat->free_ij = PETSC_TRUE;
5026dea91ad1SHong Zhang     mat->nonew   = 0;
50275a7d977cSHong Zhang   } else if (scall == MAT_REUSE_MATRIX){
50285a7d977cSHong Zhang     mat=(Mat_SeqAIJ*)(*A_loc)->data;
5029a77337e4SBarry Smith     ci = mat->i; cj = mat->j; cam = mat->a;
50305a7d977cSHong Zhang     for (i=0; i<am; i++) {
50315a7d977cSHong Zhang       /* off-diagonal portion of A */
50325a7d977cSHong Zhang       ncols_o = bi[i+1] - bi[i];
50335a7d977cSHong Zhang       for (jo=0; jo<ncols_o; jo++) {
50345a7d977cSHong Zhang         col = cmap[*bj];
50355a7d977cSHong Zhang         if (col >= cstart) break;
5036a77337e4SBarry Smith         *cam++ = *ba++; bj++;
50375a7d977cSHong Zhang       }
50385a7d977cSHong Zhang       /* diagonal portion of A */
5039ecc9b87dSHong Zhang       ncols_d = ai[i+1] - ai[i];
5040a77337e4SBarry Smith       for (j=0; j<ncols_d; j++) *cam++ = *aa++;
50415a7d977cSHong Zhang       /* off-diagonal portion of A */
5042f33d1a9aSHong Zhang       for (j=jo; j<ncols_o; j++) {
5043a77337e4SBarry Smith         *cam++ = *ba++; bj++;
5044f33d1a9aSHong Zhang       }
50455a7d977cSHong Zhang     }
50468661ff28SBarry Smith   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid MatReuse %d",(int)scall);
50474ebed01fSBarry Smith   ierr = PetscLogEventEnd(MAT_Getlocalmat,A,0,0,0);CHKERRQ(ierr);
504825616d81SHong Zhang   PetscFunctionReturn(0);
504925616d81SHong Zhang }
505025616d81SHong Zhang 
505132fba14fSHong Zhang #undef __FUNCT__
50524a2b5492SBarry Smith #define __FUNCT__ "MatMPIAIJGetLocalMatCondensed"
505332fba14fSHong Zhang /*@C
5054ba264940SBarry Smith      MatMPIAIJGetLocalMatCondensed - Creates a SeqAIJ matrix from an MPIAIJ matrix by taking all its local rows and NON-ZERO columns
505532fba14fSHong Zhang 
505632fba14fSHong Zhang     Not Collective
505732fba14fSHong Zhang 
505832fba14fSHong Zhang    Input Parameters:
505932fba14fSHong Zhang +    A - the matrix
506032fba14fSHong Zhang .    scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
506132fba14fSHong Zhang -    row, col - index sets of rows and columns to extract (or PETSC_NULL)
506232fba14fSHong Zhang 
506332fba14fSHong Zhang    Output Parameter:
506432fba14fSHong Zhang .    A_loc - the local sequential matrix generated
506532fba14fSHong Zhang 
506632fba14fSHong Zhang     Level: developer
506732fba14fSHong Zhang 
5068ba264940SBarry Smith .seealso: MatGetOwnershipRange(), MatMPIAIJGetLocalMat()
5069ba264940SBarry Smith 
507032fba14fSHong Zhang @*/
50714a2b5492SBarry Smith PetscErrorCode  MatMPIAIJGetLocalMatCondensed(Mat A,MatReuse scall,IS *row,IS *col,Mat *A_loc)
507232fba14fSHong Zhang {
507332fba14fSHong Zhang   Mat_MPIAIJ        *a=(Mat_MPIAIJ*)A->data;
507432fba14fSHong Zhang   PetscErrorCode    ierr;
507532fba14fSHong Zhang   PetscInt          i,start,end,ncols,nzA,nzB,*cmap,imark,*idx;
507632fba14fSHong Zhang   IS                isrowa,iscola;
507732fba14fSHong Zhang   Mat               *aloc;
50784a2b5492SBarry Smith   PetscBool       match;
507932fba14fSHong Zhang 
508032fba14fSHong Zhang   PetscFunctionBegin;
5081251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&match);CHKERRQ(ierr);
50824a2b5492SBarry Smith   if (!match) SETERRQ(((PetscObject)A)->comm, PETSC_ERR_SUP,"Requires MPIAIJ matrix as input");
50834ebed01fSBarry Smith   ierr = PetscLogEventBegin(MAT_Getlocalmatcondensed,A,0,0,0);CHKERRQ(ierr);
508432fba14fSHong Zhang   if (!row){
5085d0f46423SBarry Smith     start = A->rmap->rstart; end = A->rmap->rend;
508632fba14fSHong Zhang     ierr = ISCreateStride(PETSC_COMM_SELF,end-start,start,1,&isrowa);CHKERRQ(ierr);
508732fba14fSHong Zhang   } else {
508832fba14fSHong Zhang     isrowa = *row;
508932fba14fSHong Zhang   }
509032fba14fSHong Zhang   if (!col){
5091d0f46423SBarry Smith     start = A->cmap->rstart;
509232fba14fSHong Zhang     cmap  = a->garray;
5093d0f46423SBarry Smith     nzA   = a->A->cmap->n;
5094d0f46423SBarry Smith     nzB   = a->B->cmap->n;
509532fba14fSHong Zhang     ierr  = PetscMalloc((nzA+nzB)*sizeof(PetscInt), &idx);CHKERRQ(ierr);
509632fba14fSHong Zhang     ncols = 0;
509732fba14fSHong Zhang     for (i=0; i<nzB; i++) {
509832fba14fSHong Zhang       if (cmap[i] < start) idx[ncols++] = cmap[i];
509932fba14fSHong Zhang       else break;
510032fba14fSHong Zhang     }
510132fba14fSHong Zhang     imark = i;
510232fba14fSHong Zhang     for (i=0; i<nzA; i++) idx[ncols++] = start + i;
510332fba14fSHong Zhang     for (i=imark; i<nzB; i++) idx[ncols++] = cmap[i];
5104d67e408aSBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,ncols,idx,PETSC_OWN_POINTER,&iscola);CHKERRQ(ierr);
510532fba14fSHong Zhang   } else {
510632fba14fSHong Zhang     iscola = *col;
510732fba14fSHong Zhang   }
510832fba14fSHong Zhang   if (scall != MAT_INITIAL_MATRIX){
510932fba14fSHong Zhang     ierr = PetscMalloc(sizeof(Mat),&aloc);CHKERRQ(ierr);
511032fba14fSHong Zhang     aloc[0] = *A_loc;
511132fba14fSHong Zhang   }
511232fba14fSHong Zhang   ierr = MatGetSubMatrices(A,1,&isrowa,&iscola,scall,&aloc);CHKERRQ(ierr);
511332fba14fSHong Zhang   *A_loc = aloc[0];
511432fba14fSHong Zhang   ierr = PetscFree(aloc);CHKERRQ(ierr);
511532fba14fSHong Zhang   if (!row){
51166bf464f9SBarry Smith     ierr = ISDestroy(&isrowa);CHKERRQ(ierr);
511732fba14fSHong Zhang   }
511832fba14fSHong Zhang   if (!col){
51196bf464f9SBarry Smith     ierr = ISDestroy(&iscola);CHKERRQ(ierr);
512032fba14fSHong Zhang   }
51214ebed01fSBarry Smith   ierr = PetscLogEventEnd(MAT_Getlocalmatcondensed,A,0,0,0);CHKERRQ(ierr);
512232fba14fSHong Zhang   PetscFunctionReturn(0);
512332fba14fSHong Zhang }
512432fba14fSHong Zhang 
512525616d81SHong Zhang #undef __FUNCT__
512625616d81SHong Zhang #define __FUNCT__ "MatGetBrowsOfAcols"
512725616d81SHong Zhang /*@C
512832fba14fSHong Zhang     MatGetBrowsOfAcols - Creates a SeqAIJ matrix by taking rows of B that equal to nonzero columns of local A
512925616d81SHong Zhang 
513025616d81SHong Zhang     Collective on Mat
513125616d81SHong Zhang 
513225616d81SHong Zhang    Input Parameters:
5133e240928fSHong Zhang +    A,B - the matrices in mpiaij format
513425616d81SHong Zhang .    scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
513525616d81SHong Zhang -    rowb, colb - index sets of rows and columns of B to extract (or PETSC_NULL)
513625616d81SHong Zhang 
513725616d81SHong Zhang    Output Parameter:
513825616d81SHong Zhang +    rowb, colb - index sets of rows and columns of B to extract
513925616d81SHong Zhang -    B_seq - the sequential matrix generated
514025616d81SHong Zhang 
514125616d81SHong Zhang     Level: developer
514225616d81SHong Zhang 
514325616d81SHong Zhang @*/
514466bfb163SHong Zhang PetscErrorCode  MatGetBrowsOfAcols(Mat A,Mat B,MatReuse scall,IS *rowb,IS *colb,Mat *B_seq)
514525616d81SHong Zhang {
5146899cda47SBarry Smith   Mat_MPIAIJ        *a=(Mat_MPIAIJ*)A->data;
514725616d81SHong Zhang   PetscErrorCode    ierr;
5148b1d57f15SBarry Smith   PetscInt          *idx,i,start,ncols,nzA,nzB,*cmap,imark;
514925616d81SHong Zhang   IS                isrowb,iscolb;
515066bfb163SHong Zhang   Mat               *bseq=PETSC_NULL;
515125616d81SHong Zhang 
515225616d81SHong Zhang   PetscFunctionBegin;
5153d0f46423SBarry Smith   if (A->cmap->rstart != B->rmap->rstart || A->cmap->rend != B->rmap->rend){
5154e32f2f54SBarry Smith     SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Matrix local dimensions are incompatible, (%D, %D) != (%D,%D)",A->cmap->rstart,A->cmap->rend,B->rmap->rstart,B->rmap->rend);
515525616d81SHong Zhang   }
51564ebed01fSBarry Smith   ierr = PetscLogEventBegin(MAT_GetBrowsOfAcols,A,B,0,0);CHKERRQ(ierr);
515725616d81SHong Zhang 
515825616d81SHong Zhang   if (scall == MAT_INITIAL_MATRIX){
5159d0f46423SBarry Smith     start = A->cmap->rstart;
516025616d81SHong Zhang     cmap  = a->garray;
5161d0f46423SBarry Smith     nzA   = a->A->cmap->n;
5162d0f46423SBarry Smith     nzB   = a->B->cmap->n;
5163b1d57f15SBarry Smith     ierr  = PetscMalloc((nzA+nzB)*sizeof(PetscInt), &idx);CHKERRQ(ierr);
516425616d81SHong Zhang     ncols = 0;
51650390132cSHong Zhang     for (i=0; i<nzB; i++) {  /* row < local row index */
516625616d81SHong Zhang       if (cmap[i] < start) idx[ncols++] = cmap[i];
516725616d81SHong Zhang       else break;
516825616d81SHong Zhang     }
516925616d81SHong Zhang     imark = i;
51700390132cSHong Zhang     for (i=0; i<nzA; i++) idx[ncols++] = start + i;  /* local rows */
51710390132cSHong Zhang     for (i=imark; i<nzB; i++) idx[ncols++] = cmap[i]; /* row > local row index */
5172d67e408aSBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,ncols,idx,PETSC_OWN_POINTER,&isrowb);CHKERRQ(ierr);
5173d0f46423SBarry Smith     ierr = ISCreateStride(PETSC_COMM_SELF,B->cmap->N,0,1,&iscolb);CHKERRQ(ierr);
517425616d81SHong Zhang   } else {
5175e32f2f54SBarry Smith     if (!rowb || !colb) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"IS rowb and colb must be provided for MAT_REUSE_MATRIX");
517625616d81SHong Zhang     isrowb = *rowb; iscolb = *colb;
517725616d81SHong Zhang     ierr = PetscMalloc(sizeof(Mat),&bseq);CHKERRQ(ierr);
517825616d81SHong Zhang     bseq[0] = *B_seq;
517925616d81SHong Zhang   }
518025616d81SHong Zhang   ierr = MatGetSubMatrices(B,1,&isrowb,&iscolb,scall,&bseq);CHKERRQ(ierr);
518125616d81SHong Zhang   *B_seq = bseq[0];
518225616d81SHong Zhang   ierr = PetscFree(bseq);CHKERRQ(ierr);
518325616d81SHong Zhang   if (!rowb){
51846bf464f9SBarry Smith     ierr = ISDestroy(&isrowb);CHKERRQ(ierr);
518525616d81SHong Zhang   } else {
518625616d81SHong Zhang     *rowb = isrowb;
518725616d81SHong Zhang   }
518825616d81SHong Zhang   if (!colb){
51896bf464f9SBarry Smith     ierr = ISDestroy(&iscolb);CHKERRQ(ierr);
519025616d81SHong Zhang   } else {
519125616d81SHong Zhang     *colb = iscolb;
519225616d81SHong Zhang   }
51934ebed01fSBarry Smith   ierr = PetscLogEventEnd(MAT_GetBrowsOfAcols,A,B,0,0);CHKERRQ(ierr);
519425616d81SHong Zhang   PetscFunctionReturn(0);
519525616d81SHong Zhang }
5196429d309bSHong Zhang 
5197a61c8c0fSHong Zhang #undef __FUNCT__
5198f8487c73SHong Zhang #define __FUNCT__ "MatGetBrowsOfAoCols_MPIAIJ"
5199f8487c73SHong Zhang /*
5200f8487c73SHong Zhang     MatGetBrowsOfAoCols_MPIAIJ - Creates a SeqAIJ matrix by taking rows of B that equal to nonzero columns
520101b7ae99SHong Zhang     of the OFF-DIAGONAL portion of local A
5202429d309bSHong Zhang 
5203429d309bSHong Zhang     Collective on Mat
5204429d309bSHong Zhang 
5205429d309bSHong Zhang    Input Parameters:
5206429d309bSHong Zhang +    A,B - the matrices in mpiaij format
5207598bc09dSHong Zhang -    scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
5208429d309bSHong Zhang 
5209429d309bSHong Zhang    Output Parameter:
5210b7f45c76SHong Zhang +    startsj_s - starting point in B's sending j-arrays, saved for MAT_REUSE (or PETSC_NULL)
5211b7f45c76SHong Zhang .    startsj_r - starting point in B's receiving j-arrays, saved for MAT_REUSE (or PETSC_NULL)
5212598bc09dSHong Zhang .    bufa_ptr - array for sending matrix values, saved for MAT_REUSE (or PETSC_NULL)
5213598bc09dSHong Zhang -    B_oth - the sequential matrix generated with size aBn=a->B->cmap->n by B->cmap->N
5214429d309bSHong Zhang 
5215429d309bSHong Zhang     Level: developer
5216429d309bSHong Zhang 
5217f8487c73SHong Zhang */
5218b7f45c76SHong Zhang PetscErrorCode  MatGetBrowsOfAoCols_MPIAIJ(Mat A,Mat B,MatReuse scall,PetscInt **startsj_s,PetscInt **startsj_r,MatScalar **bufa_ptr,Mat *B_oth)
5219429d309bSHong Zhang {
5220a6b2eed2SHong Zhang   VecScatter_MPI_General *gen_to,*gen_from;
5221429d309bSHong Zhang   PetscErrorCode         ierr;
5222899cda47SBarry Smith   Mat_MPIAIJ             *a=(Mat_MPIAIJ*)A->data;
522387025532SHong Zhang   Mat_SeqAIJ             *b_oth;
5224a6b2eed2SHong Zhang   VecScatter             ctx=a->Mvctx;
52257adad957SLisandro Dalcin   MPI_Comm               comm=((PetscObject)ctx)->comm;
52267adad957SLisandro Dalcin   PetscMPIInt            *rprocs,*sprocs,tag=((PetscObject)ctx)->tag,rank;
5227d0f46423SBarry Smith   PetscInt               *rowlen,*bufj,*bufJ,ncols,aBn=a->B->cmap->n,row,*b_othi,*b_othj;
5228dd6ea824SBarry Smith   PetscScalar            *rvalues,*svalues;
5229dd6ea824SBarry Smith   MatScalar              *b_otha,*bufa,*bufA;
5230e42f35eeSHong Zhang   PetscInt               i,j,k,l,ll,nrecvs,nsends,nrows,*srow,*rstarts,*rstartsj = 0,*sstarts,*sstartsj,len;
5231910ba992SMatthew Knepley   MPI_Request            *rwaits = PETSC_NULL,*swaits = PETSC_NULL;
523287025532SHong Zhang   MPI_Status             *sstatus,rstatus;
5233aa5bb8c0SSatish Balay   PetscMPIInt            jj;
5234e42f35eeSHong Zhang   PetscInt               *cols,sbs,rbs;
5235ba8c8a56SBarry Smith   PetscScalar            *vals;
5236429d309bSHong Zhang 
5237429d309bSHong Zhang   PetscFunctionBegin;
5238d0f46423SBarry Smith   if (A->cmap->rstart != B->rmap->rstart || A->cmap->rend != B->rmap->rend){
5239e32f2f54SBarry Smith     SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Matrix local dimensions are incompatible, (%d, %d) != (%d,%d)",A->cmap->rstart,A->cmap->rend,B->rmap->rstart,B->rmap->rend);
5240429d309bSHong Zhang   }
52414ebed01fSBarry Smith   ierr = PetscLogEventBegin(MAT_GetBrowsOfAocols,A,B,0,0);CHKERRQ(ierr);
5242a6b2eed2SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
5243a6b2eed2SHong Zhang 
5244a6b2eed2SHong Zhang   gen_to   = (VecScatter_MPI_General*)ctx->todata;
5245a6b2eed2SHong Zhang   gen_from = (VecScatter_MPI_General*)ctx->fromdata;
5246e42f35eeSHong Zhang   rvalues  = gen_from->values; /* holds the length of receiving row */
5247e42f35eeSHong Zhang   svalues  = gen_to->values;   /* holds the length of sending row */
5248a6b2eed2SHong Zhang   nrecvs   = gen_from->n;
5249a6b2eed2SHong Zhang   nsends   = gen_to->n;
5250d7ee0231SBarry Smith 
5251d7ee0231SBarry Smith   ierr = PetscMalloc2(nrecvs,MPI_Request,&rwaits,nsends,MPI_Request,&swaits);CHKERRQ(ierr);
5252a6b2eed2SHong Zhang   srow     = gen_to->indices;   /* local row index to be sent */
5253a6b2eed2SHong Zhang   sstarts  = gen_to->starts;
5254a6b2eed2SHong Zhang   sprocs   = gen_to->procs;
5255a6b2eed2SHong Zhang   sstatus  = gen_to->sstatus;
5256e42f35eeSHong Zhang   sbs      = gen_to->bs;
5257e42f35eeSHong Zhang   rstarts  = gen_from->starts;
5258e42f35eeSHong Zhang   rprocs   = gen_from->procs;
5259e42f35eeSHong Zhang   rbs      = gen_from->bs;
5260429d309bSHong Zhang 
5261b7f45c76SHong Zhang   if (!startsj_s || !bufa_ptr) scall = MAT_INITIAL_MATRIX;
5262429d309bSHong Zhang   if (scall == MAT_INITIAL_MATRIX){
5263a6b2eed2SHong Zhang     /* i-array */
5264a6b2eed2SHong Zhang     /*---------*/
5265a6b2eed2SHong Zhang     /*  post receives */
5266a6b2eed2SHong Zhang     for (i=0; i<nrecvs; i++){
5267e42f35eeSHong Zhang       rowlen = (PetscInt*)rvalues + rstarts[i]*rbs;
5268e42f35eeSHong Zhang       nrows = (rstarts[i+1]-rstarts[i])*rbs; /* num of indices to be received */
526987025532SHong Zhang       ierr = MPI_Irecv(rowlen,nrows,MPIU_INT,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr);
5270429d309bSHong Zhang     }
5271a6b2eed2SHong Zhang 
5272a6b2eed2SHong Zhang     /* pack the outgoing message */
52731d79065fSBarry Smith     ierr = PetscMalloc2(nsends+1,PetscInt,&sstartsj,nrecvs+1,PetscInt,&rstartsj);CHKERRQ(ierr);
5274a6b2eed2SHong Zhang     sstartsj[0] = 0;  rstartsj[0] = 0;
5275a6b2eed2SHong Zhang     len = 0; /* total length of j or a array to be sent */
5276a6b2eed2SHong Zhang     k = 0;
5277a6b2eed2SHong Zhang     for (i=0; i<nsends; i++){
5278e42f35eeSHong Zhang       rowlen = (PetscInt*)svalues + sstarts[i]*sbs;
5279e42f35eeSHong Zhang       nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */
528087025532SHong Zhang       for (j=0; j<nrows; j++) {
5281d0f46423SBarry Smith         row = srow[k] + B->rmap->range[rank]; /* global row idx */
5282e42f35eeSHong Zhang         for (l=0; l<sbs; l++){
5283e42f35eeSHong Zhang           ierr = MatGetRow_MPIAIJ(B,row+l,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); /* rowlength */
5284e42f35eeSHong Zhang           rowlen[j*sbs+l] = ncols;
5285e42f35eeSHong Zhang           len += ncols;
5286e42f35eeSHong Zhang           ierr = MatRestoreRow_MPIAIJ(B,row+l,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
5287e42f35eeSHong Zhang         }
5288a6b2eed2SHong Zhang         k++;
5289429d309bSHong Zhang       }
5290e42f35eeSHong Zhang       ierr = MPI_Isend(rowlen,nrows*sbs,MPIU_INT,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr);
5291dea91ad1SHong Zhang       sstartsj[i+1] = len;  /* starting point of (i+1)-th outgoing msg in bufj and bufa */
5292429d309bSHong Zhang     }
529387025532SHong Zhang     /* recvs and sends of i-array are completed */
529487025532SHong Zhang     i = nrecvs;
529587025532SHong Zhang     while (i--) {
5296aa5bb8c0SSatish Balay       ierr = MPI_Waitany(nrecvs,rwaits,&jj,&rstatus);CHKERRQ(ierr);
529787025532SHong Zhang     }
52980c468ba9SBarry Smith     if (nsends) {ierr = MPI_Waitall(nsends,swaits,sstatus);CHKERRQ(ierr);}
5299e42f35eeSHong Zhang 
5300a6b2eed2SHong Zhang     /* allocate buffers for sending j and a arrays */
5301a6b2eed2SHong Zhang     ierr = PetscMalloc((len+1)*sizeof(PetscInt),&bufj);CHKERRQ(ierr);
5302a6b2eed2SHong Zhang     ierr = PetscMalloc((len+1)*sizeof(PetscScalar),&bufa);CHKERRQ(ierr);
5303a6b2eed2SHong Zhang 
530487025532SHong Zhang     /* create i-array of B_oth */
530587025532SHong Zhang     ierr = PetscMalloc((aBn+2)*sizeof(PetscInt),&b_othi);CHKERRQ(ierr);
530687025532SHong Zhang     b_othi[0] = 0;
5307a6b2eed2SHong Zhang     len = 0; /* total length of j or a array to be received */
5308a6b2eed2SHong Zhang     k = 0;
5309a6b2eed2SHong Zhang     for (i=0; i<nrecvs; i++){
5310fd0ff01cSHong Zhang       rowlen = (PetscInt*)rvalues + rstarts[i]*rbs;
5311e42f35eeSHong Zhang       nrows = rbs*(rstarts[i+1]-rstarts[i]); /* num of rows to be recieved */
531287025532SHong Zhang       for (j=0; j<nrows; j++) {
531387025532SHong Zhang         b_othi[k+1] = b_othi[k] + rowlen[j];
5314a6b2eed2SHong Zhang         len += rowlen[j]; k++;
5315a6b2eed2SHong Zhang       }
5316dea91ad1SHong Zhang       rstartsj[i+1] = len; /* starting point of (i+1)-th incoming msg in bufj and bufa */
5317a6b2eed2SHong Zhang     }
5318a6b2eed2SHong Zhang 
531987025532SHong Zhang     /* allocate space for j and a arrrays of B_oth */
532087025532SHong Zhang     ierr = PetscMalloc((b_othi[aBn]+1)*sizeof(PetscInt),&b_othj);CHKERRQ(ierr);
5321dd6ea824SBarry Smith     ierr = PetscMalloc((b_othi[aBn]+1)*sizeof(MatScalar),&b_otha);CHKERRQ(ierr);
5322a6b2eed2SHong Zhang 
532387025532SHong Zhang     /* j-array */
532487025532SHong Zhang     /*---------*/
5325a6b2eed2SHong Zhang     /*  post receives of j-array */
5326a6b2eed2SHong Zhang     for (i=0; i<nrecvs; i++){
532787025532SHong Zhang       nrows = rstartsj[i+1]-rstartsj[i]; /* length of the msg received */
532887025532SHong Zhang       ierr = MPI_Irecv(b_othj+rstartsj[i],nrows,MPIU_INT,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr);
5329a6b2eed2SHong Zhang     }
5330e42f35eeSHong Zhang 
5331e42f35eeSHong Zhang     /* pack the outgoing message j-array */
5332a6b2eed2SHong Zhang     k = 0;
5333a6b2eed2SHong Zhang     for (i=0; i<nsends; i++){
5334e42f35eeSHong Zhang       nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */
5335a6b2eed2SHong Zhang       bufJ = bufj+sstartsj[i];
533687025532SHong Zhang       for (j=0; j<nrows; j++) {
5337d0f46423SBarry Smith         row  = srow[k++] + B->rmap->range[rank]; /* global row idx */
5338e42f35eeSHong Zhang         for (ll=0; ll<sbs; ll++){
5339e42f35eeSHong Zhang           ierr = MatGetRow_MPIAIJ(B,row+ll,&ncols,&cols,PETSC_NULL);CHKERRQ(ierr);
5340a6b2eed2SHong Zhang           for (l=0; l<ncols; l++){
5341a6b2eed2SHong Zhang             *bufJ++ = cols[l];
534287025532SHong Zhang           }
5343e42f35eeSHong Zhang           ierr = MatRestoreRow_MPIAIJ(B,row+ll,&ncols,&cols,PETSC_NULL);CHKERRQ(ierr);
5344e42f35eeSHong Zhang         }
534587025532SHong Zhang       }
534687025532SHong Zhang       ierr = MPI_Isend(bufj+sstartsj[i],sstartsj[i+1]-sstartsj[i],MPIU_INT,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr);
534787025532SHong Zhang     }
534887025532SHong Zhang 
534987025532SHong Zhang     /* recvs and sends of j-array are completed */
535087025532SHong Zhang     i = nrecvs;
535187025532SHong Zhang     while (i--) {
5352aa5bb8c0SSatish Balay       ierr = MPI_Waitany(nrecvs,rwaits,&jj,&rstatus);CHKERRQ(ierr);
535387025532SHong Zhang     }
53540c468ba9SBarry Smith     if (nsends) {ierr = MPI_Waitall(nsends,swaits,sstatus);CHKERRQ(ierr);}
535587025532SHong Zhang   } else if (scall == MAT_REUSE_MATRIX){
5356b7f45c76SHong Zhang     sstartsj = *startsj_s;
53571d79065fSBarry Smith     rstartsj = *startsj_r;
535887025532SHong Zhang     bufa     = *bufa_ptr;
535987025532SHong Zhang     b_oth    = (Mat_SeqAIJ*)(*B_oth)->data;
536087025532SHong Zhang     b_otha   = b_oth->a;
536187025532SHong Zhang   } else {
5362e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Matrix P does not posses an object container");
536387025532SHong Zhang   }
536487025532SHong Zhang 
536587025532SHong Zhang   /* a-array */
536687025532SHong Zhang   /*---------*/
536787025532SHong Zhang   /*  post receives of a-array */
536887025532SHong Zhang   for (i=0; i<nrecvs; i++){
536987025532SHong Zhang     nrows = rstartsj[i+1]-rstartsj[i]; /* length of the msg received */
537087025532SHong Zhang     ierr = MPI_Irecv(b_otha+rstartsj[i],nrows,MPIU_SCALAR,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr);
537187025532SHong Zhang   }
5372e42f35eeSHong Zhang 
5373e42f35eeSHong Zhang   /* pack the outgoing message a-array */
537487025532SHong Zhang   k = 0;
537587025532SHong Zhang   for (i=0; i<nsends; i++){
5376e42f35eeSHong Zhang     nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */
537787025532SHong Zhang     bufA = bufa+sstartsj[i];
537887025532SHong Zhang     for (j=0; j<nrows; j++) {
5379d0f46423SBarry Smith       row  = srow[k++] + B->rmap->range[rank]; /* global row idx */
5380e42f35eeSHong Zhang       for (ll=0; ll<sbs; ll++){
5381e42f35eeSHong Zhang         ierr = MatGetRow_MPIAIJ(B,row+ll,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr);
538287025532SHong Zhang         for (l=0; l<ncols; l++){
5383a6b2eed2SHong Zhang           *bufA++ = vals[l];
5384a6b2eed2SHong Zhang         }
5385e42f35eeSHong Zhang         ierr = MatRestoreRow_MPIAIJ(B,row+ll,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr);
5386e42f35eeSHong Zhang       }
5387a6b2eed2SHong Zhang     }
538887025532SHong Zhang     ierr = MPI_Isend(bufa+sstartsj[i],sstartsj[i+1]-sstartsj[i],MPIU_SCALAR,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr);
5389a6b2eed2SHong Zhang   }
539087025532SHong Zhang   /* recvs and sends of a-array are completed */
539187025532SHong Zhang   i = nrecvs;
539287025532SHong Zhang   while (i--) {
5393aa5bb8c0SSatish Balay     ierr = MPI_Waitany(nrecvs,rwaits,&jj,&rstatus);CHKERRQ(ierr);
539487025532SHong Zhang   }
53950c468ba9SBarry Smith   if (nsends) {ierr = MPI_Waitall(nsends,swaits,sstatus);CHKERRQ(ierr);}
5396d7ee0231SBarry Smith   ierr = PetscFree2(rwaits,swaits);CHKERRQ(ierr);
5397a6b2eed2SHong Zhang 
539887025532SHong Zhang   if (scall == MAT_INITIAL_MATRIX){
5399a6b2eed2SHong Zhang     /* put together the new matrix */
5400d0f46423SBarry Smith     ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,aBn,B->cmap->N,b_othi,b_othj,b_otha,B_oth);CHKERRQ(ierr);
5401a6b2eed2SHong Zhang 
5402a6b2eed2SHong Zhang     /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */
5403a6b2eed2SHong Zhang     /* Since these are PETSc arrays, change flags to free them as necessary. */
540487025532SHong Zhang     b_oth          = (Mat_SeqAIJ *)(*B_oth)->data;
5405e6b907acSBarry Smith     b_oth->free_a  = PETSC_TRUE;
5406e6b907acSBarry Smith     b_oth->free_ij = PETSC_TRUE;
540787025532SHong Zhang     b_oth->nonew   = 0;
5408a6b2eed2SHong Zhang 
5409a6b2eed2SHong Zhang     ierr = PetscFree(bufj);CHKERRQ(ierr);
5410b7f45c76SHong Zhang     if (!startsj_s || !bufa_ptr){
54111d79065fSBarry Smith       ierr = PetscFree2(sstartsj,rstartsj);CHKERRQ(ierr);
5412dea91ad1SHong Zhang       ierr = PetscFree(bufa_ptr);CHKERRQ(ierr);
5413dea91ad1SHong Zhang     } else {
5414b7f45c76SHong Zhang       *startsj_s = sstartsj;
54151d79065fSBarry Smith       *startsj_r = rstartsj;
541687025532SHong Zhang       *bufa_ptr  = bufa;
541787025532SHong Zhang     }
5418dea91ad1SHong Zhang   }
54194ebed01fSBarry Smith   ierr = PetscLogEventEnd(MAT_GetBrowsOfAocols,A,B,0,0);CHKERRQ(ierr);
5420429d309bSHong Zhang   PetscFunctionReturn(0);
5421429d309bSHong Zhang }
5422ccd8e176SBarry Smith 
542343eb5e2fSMatthew Knepley #undef __FUNCT__
542443eb5e2fSMatthew Knepley #define __FUNCT__ "MatGetCommunicationStructs"
542543eb5e2fSMatthew Knepley /*@C
542643eb5e2fSMatthew Knepley   MatGetCommunicationStructs - Provides access to the communication structures used in matrix-vector multiplication.
542743eb5e2fSMatthew Knepley 
542843eb5e2fSMatthew Knepley   Not Collective
542943eb5e2fSMatthew Knepley 
543043eb5e2fSMatthew Knepley   Input Parameters:
543143eb5e2fSMatthew Knepley . A - The matrix in mpiaij format
543243eb5e2fSMatthew Knepley 
543343eb5e2fSMatthew Knepley   Output Parameter:
543443eb5e2fSMatthew Knepley + lvec - The local vector holding off-process values from the argument to a matrix-vector product
543543eb5e2fSMatthew Knepley . colmap - A map from global column index to local index into lvec
543643eb5e2fSMatthew Knepley - multScatter - A scatter from the argument of a matrix-vector product to lvec
543743eb5e2fSMatthew Knepley 
543843eb5e2fSMatthew Knepley   Level: developer
543943eb5e2fSMatthew Knepley 
544043eb5e2fSMatthew Knepley @*/
544143eb5e2fSMatthew Knepley #if defined (PETSC_USE_CTABLE)
54427087cfbeSBarry Smith PetscErrorCode  MatGetCommunicationStructs(Mat A, Vec *lvec, PetscTable *colmap, VecScatter *multScatter)
544343eb5e2fSMatthew Knepley #else
54447087cfbeSBarry Smith PetscErrorCode  MatGetCommunicationStructs(Mat A, Vec *lvec, PetscInt *colmap[], VecScatter *multScatter)
544543eb5e2fSMatthew Knepley #endif
544643eb5e2fSMatthew Knepley {
544743eb5e2fSMatthew Knepley   Mat_MPIAIJ *a;
544843eb5e2fSMatthew Knepley 
544943eb5e2fSMatthew Knepley   PetscFunctionBegin;
54500700a824SBarry Smith   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5451e414b56bSJed Brown   PetscValidPointer(lvec, 2);
5452e414b56bSJed Brown   PetscValidPointer(colmap, 3);
5453e414b56bSJed Brown   PetscValidPointer(multScatter, 4);
545443eb5e2fSMatthew Knepley   a = (Mat_MPIAIJ *) A->data;
545543eb5e2fSMatthew Knepley   if (lvec) *lvec = a->lvec;
545643eb5e2fSMatthew Knepley   if (colmap) *colmap = a->colmap;
545743eb5e2fSMatthew Knepley   if (multScatter) *multScatter = a->Mvctx;
545843eb5e2fSMatthew Knepley   PetscFunctionReturn(0);
545943eb5e2fSMatthew Knepley }
546043eb5e2fSMatthew Knepley 
546117667f90SBarry Smith EXTERN_C_BEGIN
54627087cfbeSBarry Smith extern PetscErrorCode  MatConvert_MPIAIJ_MPIAIJCRL(Mat,const MatType,MatReuse,Mat*);
54637087cfbeSBarry Smith extern PetscErrorCode  MatConvert_MPIAIJ_MPIAIJPERM(Mat,const MatType,MatReuse,Mat*);
54647087cfbeSBarry Smith extern PetscErrorCode  MatConvert_MPIAIJ_MPISBAIJ(Mat,const MatType,MatReuse,Mat*);
546517667f90SBarry Smith EXTERN_C_END
546617667f90SBarry Smith 
5467fc4dec0aSBarry Smith #undef __FUNCT__
5468fc4dec0aSBarry Smith #define __FUNCT__ "MatMatMultNumeric_MPIDense_MPIAIJ"
5469fc4dec0aSBarry Smith /*
5470fc4dec0aSBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
5471fc4dec0aSBarry Smith 
5472fc4dec0aSBarry Smith                n                       p                          p
5473fc4dec0aSBarry Smith         (              )       (              )         (                  )
5474fc4dec0aSBarry Smith       m (      A       )  *  n (       B      )   =   m (         C        )
5475fc4dec0aSBarry Smith         (              )       (              )         (                  )
5476fc4dec0aSBarry Smith 
5477fc4dec0aSBarry Smith */
5478fc4dec0aSBarry Smith PetscErrorCode MatMatMultNumeric_MPIDense_MPIAIJ(Mat A,Mat B,Mat C)
5479fc4dec0aSBarry Smith {
5480fc4dec0aSBarry Smith   PetscErrorCode     ierr;
5481fc4dec0aSBarry Smith   Mat                At,Bt,Ct;
5482fc4dec0aSBarry Smith 
5483fc4dec0aSBarry Smith   PetscFunctionBegin;
5484fc4dec0aSBarry Smith   ierr = MatTranspose(A,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr);
5485fc4dec0aSBarry Smith   ierr = MatTranspose(B,MAT_INITIAL_MATRIX,&Bt);CHKERRQ(ierr);
5486fc4dec0aSBarry Smith   ierr = MatMatMult(Bt,At,MAT_INITIAL_MATRIX,1.0,&Ct);CHKERRQ(ierr);
54876bf464f9SBarry Smith   ierr = MatDestroy(&At);CHKERRQ(ierr);
54886bf464f9SBarry Smith   ierr = MatDestroy(&Bt);CHKERRQ(ierr);
5489fc4dec0aSBarry Smith   ierr = MatTranspose(Ct,MAT_REUSE_MATRIX,&C);CHKERRQ(ierr);
54906bf464f9SBarry Smith   ierr = MatDestroy(&Ct);CHKERRQ(ierr);
5491fc4dec0aSBarry Smith   PetscFunctionReturn(0);
5492fc4dec0aSBarry Smith }
5493fc4dec0aSBarry Smith 
5494fc4dec0aSBarry Smith #undef __FUNCT__
5495fc4dec0aSBarry Smith #define __FUNCT__ "MatMatMultSymbolic_MPIDense_MPIAIJ"
5496fc4dec0aSBarry Smith PetscErrorCode MatMatMultSymbolic_MPIDense_MPIAIJ(Mat A,Mat B,PetscReal fill,Mat *C)
5497fc4dec0aSBarry Smith {
5498fc4dec0aSBarry Smith   PetscErrorCode ierr;
5499d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
5500fc4dec0aSBarry Smith   Mat            Cmat;
5501fc4dec0aSBarry Smith 
5502fc4dec0aSBarry Smith   PetscFunctionBegin;
5503e32f2f54SBarry Smith   if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->rmap->n %d\n",A->cmap->n,B->rmap->n);
550439804f7cSBarry Smith   ierr = MatCreate(((PetscObject)A)->comm,&Cmat);CHKERRQ(ierr);
5505fc4dec0aSBarry Smith   ierr = MatSetSizes(Cmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
5506a2f3521dSMark F. Adams   ierr = MatSetBlockSizes(Cmat,A->rmap->bs,B->cmap->bs);CHKERRQ(ierr);
5507fc4dec0aSBarry Smith   ierr = MatSetType(Cmat,MATMPIDENSE);CHKERRQ(ierr);
5508fc4dec0aSBarry Smith   ierr = MatMPIDenseSetPreallocation(Cmat,PETSC_NULL);CHKERRQ(ierr);
550938556019SBarry Smith   ierr = MatAssemblyBegin(Cmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
551038556019SBarry Smith   ierr = MatAssemblyEnd(Cmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5511fc4dec0aSBarry Smith   *C   = Cmat;
55128cdbd757SHong Zhang   (*C)->ops->matmult = MatMatMult_MPIDense_MPIAIJ;
5513fc4dec0aSBarry Smith   PetscFunctionReturn(0);
5514fc4dec0aSBarry Smith }
5515fc4dec0aSBarry Smith 
5516fc4dec0aSBarry Smith /* ----------------------------------------------------------------*/
5517fc4dec0aSBarry Smith #undef __FUNCT__
5518fc4dec0aSBarry Smith #define __FUNCT__ "MatMatMult_MPIDense_MPIAIJ"
5519fc4dec0aSBarry Smith PetscErrorCode MatMatMult_MPIDense_MPIAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
5520fc4dec0aSBarry Smith {
5521fc4dec0aSBarry Smith   PetscErrorCode ierr;
5522fc4dec0aSBarry Smith 
5523fc4dec0aSBarry Smith   PetscFunctionBegin;
5524fc4dec0aSBarry Smith   if (scall == MAT_INITIAL_MATRIX){
5525fc4dec0aSBarry Smith     ierr = MatMatMultSymbolic_MPIDense_MPIAIJ(A,B,fill,C);CHKERRQ(ierr);
5526fc4dec0aSBarry Smith   }
5527fc4dec0aSBarry Smith   ierr = MatMatMultNumeric_MPIDense_MPIAIJ(A,B,*C);CHKERRQ(ierr);
5528fc4dec0aSBarry Smith   PetscFunctionReturn(0);
5529fc4dec0aSBarry Smith }
5530fc4dec0aSBarry Smith 
55315c9eb25fSBarry Smith EXTERN_C_BEGIN
5532611f576cSBarry Smith #if defined(PETSC_HAVE_MUMPS)
5533bccb9932SShri Abhyankar extern PetscErrorCode MatGetFactor_aij_mumps(Mat,MatFactorType,Mat*);
5534611f576cSBarry Smith #endif
55353bf14a46SMatthew Knepley #if defined(PETSC_HAVE_PASTIX)
55363bf14a46SMatthew Knepley extern PetscErrorCode MatGetFactor_mpiaij_pastix(Mat,MatFactorType,Mat*);
55373bf14a46SMatthew Knepley #endif
5538611f576cSBarry Smith #if defined(PETSC_HAVE_SUPERLU_DIST)
55395c9eb25fSBarry Smith extern PetscErrorCode MatGetFactor_mpiaij_superlu_dist(Mat,MatFactorType,Mat*);
5540611f576cSBarry Smith #endif
5541611f576cSBarry Smith #if defined(PETSC_HAVE_SPOOLES)
55425c9eb25fSBarry Smith extern PetscErrorCode MatGetFactor_mpiaij_spooles(Mat,MatFactorType,Mat*);
5543611f576cSBarry Smith #endif
554417f1a0eaSHong Zhang #if defined(PETSC_HAVE_CLIQUE)
554517f1a0eaSHong Zhang extern PetscErrorCode MatGetFactor_aij_clique(Mat,MatFactorType,Mat*);
554617f1a0eaSHong Zhang #endif
55475c9eb25fSBarry Smith EXTERN_C_END
55485c9eb25fSBarry Smith 
5549ccd8e176SBarry Smith /*MC
5550ccd8e176SBarry Smith    MATMPIAIJ - MATMPIAIJ = "mpiaij" - A matrix type to be used for parallel sparse matrices.
5551ccd8e176SBarry Smith 
5552ccd8e176SBarry Smith    Options Database Keys:
5553ccd8e176SBarry Smith . -mat_type mpiaij - sets the matrix type to "mpiaij" during a call to MatSetFromOptions()
5554ccd8e176SBarry Smith 
5555ccd8e176SBarry Smith   Level: beginner
5556ccd8e176SBarry Smith 
555769b1f4b7SBarry Smith .seealso: MatCreateAIJ()
5558ccd8e176SBarry Smith M*/
5559ccd8e176SBarry Smith 
5560ccd8e176SBarry Smith EXTERN_C_BEGIN
5561ccd8e176SBarry Smith #undef __FUNCT__
5562ccd8e176SBarry Smith #define __FUNCT__ "MatCreate_MPIAIJ"
55637087cfbeSBarry Smith PetscErrorCode  MatCreate_MPIAIJ(Mat B)
5564ccd8e176SBarry Smith {
5565ccd8e176SBarry Smith   Mat_MPIAIJ     *b;
5566ccd8e176SBarry Smith   PetscErrorCode ierr;
5567ccd8e176SBarry Smith   PetscMPIInt    size;
5568ccd8e176SBarry Smith 
5569ccd8e176SBarry Smith   PetscFunctionBegin;
55707adad957SLisandro Dalcin   ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr);
557138f2d2fdSLisandro Dalcin   ierr            = PetscNewLog(B,Mat_MPIAIJ,&b);CHKERRQ(ierr);
5572ccd8e176SBarry Smith   B->data         = (void*)b;
5573ccd8e176SBarry Smith   ierr            = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
5574ccd8e176SBarry Smith   B->assembled    = PETSC_FALSE;
5575ccd8e176SBarry Smith   B->insertmode   = NOT_SET_VALUES;
5576ccd8e176SBarry Smith   b->size         = size;
55777adad957SLisandro Dalcin   ierr = MPI_Comm_rank(((PetscObject)B)->comm,&b->rank);CHKERRQ(ierr);
5578ccd8e176SBarry Smith 
5579ccd8e176SBarry Smith   /* build cache for off array entries formed */
55807adad957SLisandro Dalcin   ierr = MatStashCreate_Private(((PetscObject)B)->comm,1,&B->stash);CHKERRQ(ierr);
5581ccd8e176SBarry Smith   b->donotstash  = PETSC_FALSE;
5582ccd8e176SBarry Smith   b->colmap      = 0;
5583ccd8e176SBarry Smith   b->garray      = 0;
5584ccd8e176SBarry Smith   b->roworiented = PETSC_TRUE;
5585ccd8e176SBarry Smith 
5586ccd8e176SBarry Smith   /* stuff used for matrix vector multiply */
5587ccd8e176SBarry Smith   b->lvec      = PETSC_NULL;
5588ccd8e176SBarry Smith   b->Mvctx     = PETSC_NULL;
5589ccd8e176SBarry Smith 
5590ccd8e176SBarry Smith   /* stuff for MatGetRow() */
5591ccd8e176SBarry Smith   b->rowindices   = 0;
5592ccd8e176SBarry Smith   b->rowvalues    = 0;
5593ccd8e176SBarry Smith   b->getrowactive = PETSC_FALSE;
5594ccd8e176SBarry Smith 
5595bbf3fe20SPaul Mullowney   /* flexible pointer used in CUSP/CUSPARSE classes */
5596bbf3fe20SPaul Mullowney   b->spptr        = PETSC_NULL;
5597611f576cSBarry Smith #if defined(PETSC_HAVE_SPOOLES)
5598ec1065edSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_spooles_C",
55995c9eb25fSBarry Smith                                      "MatGetFactor_mpiaij_spooles",
56005c9eb25fSBarry Smith                                      MatGetFactor_mpiaij_spooles);CHKERRQ(ierr);
5601611f576cSBarry Smith #endif
5602611f576cSBarry Smith #if defined(PETSC_HAVE_MUMPS)
5603ec1065edSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_mumps_C",
5604bccb9932SShri Abhyankar                                      "MatGetFactor_aij_mumps",
5605bccb9932SShri Abhyankar                                      MatGetFactor_aij_mumps);CHKERRQ(ierr);
5606611f576cSBarry Smith #endif
56073bf14a46SMatthew Knepley #if defined(PETSC_HAVE_PASTIX)
5608ec1065edSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_pastix_C",
56093bf14a46SMatthew Knepley 					   "MatGetFactor_mpiaij_pastix",
56103bf14a46SMatthew Knepley 					   MatGetFactor_mpiaij_pastix);CHKERRQ(ierr);
56113bf14a46SMatthew Knepley #endif
5612611f576cSBarry Smith #if defined(PETSC_HAVE_SUPERLU_DIST)
5613ec1065edSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_dist_C",
56145c9eb25fSBarry Smith                                      "MatGetFactor_mpiaij_superlu_dist",
56155c9eb25fSBarry Smith                                      MatGetFactor_mpiaij_superlu_dist);CHKERRQ(ierr);
5616611f576cSBarry Smith #endif
561717f1a0eaSHong Zhang #if defined(PETSC_HAVE_CLIQUE)
561817f1a0eaSHong Zhang   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_clique_C",
561917f1a0eaSHong Zhang                                      "MatGetFactor_aij_clique",
562017f1a0eaSHong Zhang                                      MatGetFactor_aij_clique);CHKERRQ(ierr);
562117f1a0eaSHong Zhang #endif
5622ccd8e176SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
5623ccd8e176SBarry Smith                                      "MatStoreValues_MPIAIJ",
5624ccd8e176SBarry Smith                                      MatStoreValues_MPIAIJ);CHKERRQ(ierr);
5625ccd8e176SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
5626ccd8e176SBarry Smith                                      "MatRetrieveValues_MPIAIJ",
5627ccd8e176SBarry Smith                                      MatRetrieveValues_MPIAIJ);CHKERRQ(ierr);
5628ccd8e176SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetDiagonalBlock_C",
5629ccd8e176SBarry Smith 				     "MatGetDiagonalBlock_MPIAIJ",
5630ccd8e176SBarry Smith                                      MatGetDiagonalBlock_MPIAIJ);CHKERRQ(ierr);
5631ccd8e176SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C",
5632ccd8e176SBarry Smith 				     "MatIsTranspose_MPIAIJ",
5633ccd8e176SBarry Smith 				     MatIsTranspose_MPIAIJ);CHKERRQ(ierr);
5634ccd8e176SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMPIAIJSetPreallocation_C",
5635ccd8e176SBarry Smith 				     "MatMPIAIJSetPreallocation_MPIAIJ",
5636ccd8e176SBarry Smith 				     MatMPIAIJSetPreallocation_MPIAIJ);CHKERRQ(ierr);
5637ccd8e176SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMPIAIJSetPreallocationCSR_C",
5638ccd8e176SBarry Smith 				     "MatMPIAIJSetPreallocationCSR_MPIAIJ",
5639ccd8e176SBarry Smith 				     MatMPIAIJSetPreallocationCSR_MPIAIJ);CHKERRQ(ierr);
5640ccd8e176SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatDiagonalScaleLocal_C",
5641ccd8e176SBarry Smith 				     "MatDiagonalScaleLocal_MPIAIJ",
5642ccd8e176SBarry Smith 				     MatDiagonalScaleLocal_MPIAIJ);CHKERRQ(ierr);
56435a11e1b2SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_mpiaij_mpiaijperm_C",
56445a11e1b2SBarry Smith                                      "MatConvert_MPIAIJ_MPIAIJPERM",
56455a11e1b2SBarry Smith                                       MatConvert_MPIAIJ_MPIAIJPERM);CHKERRQ(ierr);
56465a11e1b2SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_mpiaij_mpiaijcrl_C",
56475a11e1b2SBarry Smith                                      "MatConvert_MPIAIJ_MPIAIJCRL",
56485a11e1b2SBarry Smith                                       MatConvert_MPIAIJ_MPIAIJCRL);CHKERRQ(ierr);
5649471cc821SHong Zhang   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_mpiaij_mpisbaij_C",
5650471cc821SHong Zhang                                      "MatConvert_MPIAIJ_MPISBAIJ",
5651471cc821SHong Zhang                                       MatConvert_MPIAIJ_MPISBAIJ);CHKERRQ(ierr);
5652fc4dec0aSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMult_mpidense_mpiaij_C",
5653fc4dec0aSBarry Smith                                      "MatMatMult_MPIDense_MPIAIJ",
5654fc4dec0aSBarry Smith                                       MatMatMult_MPIDense_MPIAIJ);CHKERRQ(ierr);
5655fc4dec0aSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultSymbolic_mpidense_mpiaij_C",
5656fc4dec0aSBarry Smith                                      "MatMatMultSymbolic_MPIDense_MPIAIJ",
5657fc4dec0aSBarry Smith                                      MatMatMultSymbolic_MPIDense_MPIAIJ);CHKERRQ(ierr);
5658fc4dec0aSBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultNumeric_mpidense_mpiaij_C",
5659fc4dec0aSBarry Smith                                      "MatMatMultNumeric_MPIDense_MPIAIJ",
5660fc4dec0aSBarry Smith                                       MatMatMultNumeric_MPIDense_MPIAIJ);CHKERRQ(ierr);
566117667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATMPIAIJ);CHKERRQ(ierr);
5662ccd8e176SBarry Smith   PetscFunctionReturn(0);
5663ccd8e176SBarry Smith }
5664ccd8e176SBarry Smith EXTERN_C_END
566581824310SBarry Smith 
566603bfb495SBarry Smith #undef __FUNCT__
566703bfb495SBarry Smith #define __FUNCT__ "MatCreateMPIAIJWithSplitArrays"
566858d36128SBarry Smith /*@
566903bfb495SBarry Smith      MatCreateMPIAIJWithSplitArrays - creates a MPI AIJ matrix using arrays that contain the "diagonal"
567003bfb495SBarry Smith          and "off-diagonal" part of the matrix in CSR format.
567103bfb495SBarry Smith 
567203bfb495SBarry Smith    Collective on MPI_Comm
567303bfb495SBarry Smith 
567403bfb495SBarry Smith    Input Parameters:
567503bfb495SBarry Smith +  comm - MPI communicator
567603bfb495SBarry Smith .  m - number of local rows (Cannot be PETSC_DECIDE)
567703bfb495SBarry Smith .  n - This value should be the same as the local size used in creating the
567803bfb495SBarry Smith        x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have
567903bfb495SBarry Smith        calculated if N is given) For square matrices n is almost always m.
568003bfb495SBarry Smith .  M - number of global rows (or PETSC_DETERMINE to have calculated if m is given)
568103bfb495SBarry Smith .  N - number of global columns (or PETSC_DETERMINE to have calculated if n is given)
568203bfb495SBarry Smith .   i - row indices for "diagonal" portion of matrix
568303bfb495SBarry Smith .   j - column indices
568403bfb495SBarry Smith .   a - matrix values
568503bfb495SBarry Smith .   oi - row indices for "off-diagonal" portion of matrix
568603bfb495SBarry Smith .   oj - column indices
568703bfb495SBarry Smith -   oa - matrix values
568803bfb495SBarry Smith 
568903bfb495SBarry Smith    Output Parameter:
569003bfb495SBarry Smith .   mat - the matrix
569103bfb495SBarry Smith 
569203bfb495SBarry Smith    Level: advanced
569303bfb495SBarry Smith 
569403bfb495SBarry Smith    Notes:
5695292fb18eSBarry Smith        The i, j, and a arrays ARE NOT copied by this routine into the internal format used by PETSc. The user
5696292fb18eSBarry Smith        must free the arrays once the matrix has been destroyed and not before.
569703bfb495SBarry Smith 
569803bfb495SBarry Smith        The i and j indices are 0 based
569903bfb495SBarry Smith 
570069b1f4b7SBarry Smith        See MatCreateAIJ() for the definition of "diagonal" and "off-diagonal" portion of the matrix
570103bfb495SBarry Smith 
57027b55108eSBarry Smith        This sets local rows and cannot be used to set off-processor values.
57037b55108eSBarry Smith 
57047b55108eSBarry Smith        You cannot later use MatSetValues() to change values in this matrix.
570503bfb495SBarry Smith 
570603bfb495SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel
570703bfb495SBarry Smith 
570803bfb495SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(),
570969b1f4b7SBarry Smith           MPIAIJ, MatCreateAIJ(), MatCreateMPIAIJWithArrays()
571003bfb495SBarry Smith @*/
57117087cfbeSBarry Smith PetscErrorCode  MatCreateMPIAIJWithSplitArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscInt i[],PetscInt j[],PetscScalar a[],
571203bfb495SBarry Smith 								PetscInt oi[], PetscInt oj[],PetscScalar oa[],Mat *mat)
571303bfb495SBarry Smith {
571403bfb495SBarry Smith   PetscErrorCode ierr;
571503bfb495SBarry Smith   Mat_MPIAIJ     *maij;
571603bfb495SBarry Smith 
571703bfb495SBarry Smith  PetscFunctionBegin;
5718e32f2f54SBarry Smith   if (m < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"local number of rows (m) cannot be PETSC_DECIDE, or negative");
5719ea345e14SBarry Smith   if (i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
5720ea345e14SBarry Smith   if (oi[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"oi (row indices) must start with 0");
572103bfb495SBarry Smith   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
572203bfb495SBarry Smith   ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr);
572303bfb495SBarry Smith   ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr);
572403bfb495SBarry Smith   maij = (Mat_MPIAIJ*) (*mat)->data;
57258d7a6e47SBarry Smith   maij->donotstash     = PETSC_TRUE;
57268d7a6e47SBarry Smith   (*mat)->preallocated = PETSC_TRUE;
572703bfb495SBarry Smith 
572826283091SBarry Smith   ierr = PetscLayoutSetUp((*mat)->rmap);CHKERRQ(ierr);
572926283091SBarry Smith   ierr = PetscLayoutSetUp((*mat)->cmap);CHKERRQ(ierr);
573003bfb495SBarry Smith 
573103bfb495SBarry Smith   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,m,n,i,j,a,&maij->A);CHKERRQ(ierr);
5732d0f46423SBarry Smith   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,m,(*mat)->cmap->N,oi,oj,oa,&maij->B);CHKERRQ(ierr);
573303bfb495SBarry Smith 
57348d7a6e47SBarry Smith   ierr = MatAssemblyBegin(maij->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57358d7a6e47SBarry Smith   ierr = MatAssemblyEnd(maij->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57368d7a6e47SBarry Smith   ierr = MatAssemblyBegin(maij->B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57378d7a6e47SBarry Smith   ierr = MatAssemblyEnd(maij->B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57388d7a6e47SBarry Smith 
573903bfb495SBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
574003bfb495SBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
574103bfb495SBarry Smith   PetscFunctionReturn(0);
574203bfb495SBarry Smith }
574303bfb495SBarry Smith 
574481824310SBarry Smith /*
574581824310SBarry Smith     Special version for direct calls from Fortran
574681824310SBarry Smith */
5747b45d2f2cSJed Brown #include <petsc-private/fortranimpl.h>
57487087cfbeSBarry Smith 
574981824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
575081824310SBarry Smith #define matsetvaluesmpiaij_ MATSETVALUESMPIAIJ
575181824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
575281824310SBarry Smith #define matsetvaluesmpiaij_ matsetvaluesmpiaij
575381824310SBarry Smith #endif
575481824310SBarry Smith 
575581824310SBarry Smith /* Change these macros so can be used in void function */
575681824310SBarry Smith #undef CHKERRQ
5757e32f2f54SBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PETSC_COMM_WORLD,ierr)
575881824310SBarry Smith #undef SETERRQ2
5759e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
57604994cf47SJed Brown #undef SETERRQ3
57614994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
576281824310SBarry Smith #undef SETERRQ
5763e32f2f54SBarry Smith #define SETERRQ(c,ierr,b) CHKERRABORT(c,ierr)
576481824310SBarry Smith 
576581824310SBarry Smith EXTERN_C_BEGIN
576681824310SBarry Smith #undef __FUNCT__
576781824310SBarry Smith #define __FUNCT__ "matsetvaluesmpiaij_"
57681f6cc5b2SSatish Balay void PETSC_STDCALL matsetvaluesmpiaij_(Mat *mmat,PetscInt *mm,const PetscInt im[],PetscInt *mn,const PetscInt in[],const PetscScalar v[],InsertMode *maddv,PetscErrorCode *_ierr)
576981824310SBarry Smith {
577081824310SBarry Smith   Mat             mat = *mmat;
577181824310SBarry Smith   PetscInt        m = *mm, n = *mn;
577281824310SBarry Smith   InsertMode      addv = *maddv;
577381824310SBarry Smith   Mat_MPIAIJ      *aij = (Mat_MPIAIJ*)mat->data;
577481824310SBarry Smith   PetscScalar     value;
577581824310SBarry Smith   PetscErrorCode  ierr;
5776899cda47SBarry Smith 
57774994cf47SJed Brown   MatCheckPreallocated(mat,1);
577881824310SBarry Smith   if (mat->insertmode == NOT_SET_VALUES) {
577981824310SBarry Smith     mat->insertmode = addv;
578081824310SBarry Smith   }
578181824310SBarry Smith #if defined(PETSC_USE_DEBUG)
578281824310SBarry Smith   else if (mat->insertmode != addv) {
5783e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values");
578481824310SBarry Smith   }
578581824310SBarry Smith #endif
578681824310SBarry Smith   {
5787d0f46423SBarry Smith   PetscInt        i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend;
5788d0f46423SBarry Smith   PetscInt        cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col;
5789ace3abfcSBarry Smith   PetscBool       roworiented = aij->roworiented;
579081824310SBarry Smith 
579181824310SBarry Smith   /* Some Variables required in the macro */
579281824310SBarry Smith   Mat             A = aij->A;
579381824310SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
579481824310SBarry Smith   PetscInt        *aimax = a->imax,*ai = a->i,*ailen = a->ilen,*aj = a->j;
5795dd6ea824SBarry Smith   MatScalar       *aa = a->a;
5796ace3abfcSBarry Smith   PetscBool       ignorezeroentries = (((a->ignorezeroentries)&&(addv==ADD_VALUES))?PETSC_TRUE:PETSC_FALSE);
579781824310SBarry Smith   Mat             B = aij->B;
579881824310SBarry Smith   Mat_SeqAIJ      *b = (Mat_SeqAIJ*)B->data;
5799d0f46423SBarry Smith   PetscInt        *bimax = b->imax,*bi = b->i,*bilen = b->ilen,*bj = b->j,bm = aij->B->rmap->n,am = aij->A->rmap->n;
5800dd6ea824SBarry Smith   MatScalar       *ba = b->a;
580181824310SBarry Smith 
580281824310SBarry Smith   PetscInt        *rp1,*rp2,ii,nrow1,nrow2,_i,rmax1,rmax2,N,low1,high1,low2,high2,t,lastcol1,lastcol2;
580381824310SBarry Smith   PetscInt        nonew = a->nonew;
5804dd6ea824SBarry Smith   MatScalar       *ap1,*ap2;
580581824310SBarry Smith 
580681824310SBarry Smith   PetscFunctionBegin;
580781824310SBarry Smith   for (i=0; i<m; i++) {
580881824310SBarry Smith     if (im[i] < 0) continue;
580981824310SBarry Smith #if defined(PETSC_USE_DEBUG)
5810e32f2f54SBarry Smith     if (im[i] >= mat->rmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",im[i],mat->rmap->N-1);
581181824310SBarry Smith #endif
581281824310SBarry Smith     if (im[i] >= rstart && im[i] < rend) {
581381824310SBarry Smith       row      = im[i] - rstart;
581481824310SBarry Smith       lastcol1 = -1;
581581824310SBarry Smith       rp1      = aj + ai[row];
581681824310SBarry Smith       ap1      = aa + ai[row];
581781824310SBarry Smith       rmax1    = aimax[row];
581881824310SBarry Smith       nrow1    = ailen[row];
581981824310SBarry Smith       low1     = 0;
582081824310SBarry Smith       high1    = nrow1;
582181824310SBarry Smith       lastcol2 = -1;
582281824310SBarry Smith       rp2      = bj + bi[row];
582381824310SBarry Smith       ap2      = ba + bi[row];
582481824310SBarry Smith       rmax2    = bimax[row];
582581824310SBarry Smith       nrow2    = bilen[row];
582681824310SBarry Smith       low2     = 0;
582781824310SBarry Smith       high2    = nrow2;
582881824310SBarry Smith 
582981824310SBarry Smith       for (j=0; j<n; j++) {
583081824310SBarry Smith         if (roworiented) value = v[i*n+j]; else value = v[i+j*m];
583181824310SBarry Smith         if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue;
583281824310SBarry Smith         if (in[j] >= cstart && in[j] < cend){
583381824310SBarry Smith           col = in[j] - cstart;
583481824310SBarry Smith           MatSetValues_SeqAIJ_A_Private(row,col,value,addv);
583581824310SBarry Smith         } else if (in[j] < 0) continue;
583681824310SBarry Smith #if defined(PETSC_USE_DEBUG)
5837cb9801acSJed Brown         else if (in[j] >= mat->cmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[j],mat->cmap->N-1);
583881824310SBarry Smith #endif
583981824310SBarry Smith         else {
584081824310SBarry Smith           if (mat->was_assembled) {
584181824310SBarry Smith             if (!aij->colmap) {
5842ab9863d7SBarry Smith               ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr);
584381824310SBarry Smith             }
584481824310SBarry Smith #if defined (PETSC_USE_CTABLE)
584581824310SBarry Smith             ierr = PetscTableFind(aij->colmap,in[j]+1,&col);CHKERRQ(ierr);
584681824310SBarry Smith 	    col--;
584781824310SBarry Smith #else
584881824310SBarry Smith             col = aij->colmap[in[j]] - 1;
584981824310SBarry Smith #endif
585081824310SBarry Smith             if (col < 0 && !((Mat_SeqAIJ*)(aij->A->data))->nonew) {
5851ab9863d7SBarry Smith               ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr);
585281824310SBarry Smith               col =  in[j];
585381824310SBarry Smith               /* Reinitialize the variables required by MatSetValues_SeqAIJ_B_Private() */
585481824310SBarry Smith               B = aij->B;
585581824310SBarry Smith               b = (Mat_SeqAIJ*)B->data;
585681824310SBarry Smith               bimax = b->imax; bi = b->i; bilen = b->ilen; bj = b->j;
585781824310SBarry Smith               rp2      = bj + bi[row];
585881824310SBarry Smith               ap2      = ba + bi[row];
585981824310SBarry Smith               rmax2    = bimax[row];
586081824310SBarry Smith               nrow2    = bilen[row];
586181824310SBarry Smith               low2     = 0;
586281824310SBarry Smith               high2    = nrow2;
5863d0f46423SBarry Smith               bm       = aij->B->rmap->n;
586481824310SBarry Smith               ba = b->a;
586581824310SBarry Smith             }
586681824310SBarry Smith           } else col = in[j];
586781824310SBarry Smith           MatSetValues_SeqAIJ_B_Private(row,col,value,addv);
586881824310SBarry Smith         }
586981824310SBarry Smith       }
587081824310SBarry Smith     } else {
587181824310SBarry Smith       if (!aij->donotstash) {
587281824310SBarry Smith         if (roworiented) {
5873ace3abfcSBarry Smith           ierr = MatStashValuesRow_Private(&mat->stash,im[i],n,in,v+i*n,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr);
587481824310SBarry Smith         } else {
5875ace3abfcSBarry Smith           ierr = MatStashValuesCol_Private(&mat->stash,im[i],n,in,v+i,m,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr);
587681824310SBarry Smith         }
587781824310SBarry Smith       }
587881824310SBarry Smith     }
587981824310SBarry Smith   }}
588081824310SBarry Smith   PetscFunctionReturnVoid();
588181824310SBarry Smith }
588281824310SBarry Smith EXTERN_C_END
588303bfb495SBarry Smith 
5884