xref: /petsc/src/mat/impls/sell/mpi/mpisell.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
1 #include <../src/mat/impls/aij/mpi/mpiaij.h>   /*I "petscmat.h" I*/
2 #include <../src/mat/impls/sell/mpi/mpisell.h>   /*I "petscmat.h" I*/
3 #include <petsc/private/vecimpl.h>
4 #include <petsc/private/isimpl.h>
5 #include <petscblaslapack.h>
6 #include <petscsf.h>
7 
8 /*MC
9    MATSELL - MATSELL = "sell" - A matrix type to be used for sparse matrices.
10 
11    This matrix type is identical to MATSEQSELL when constructed with a single process communicator,
12    and MATMPISELL otherwise.  As a result, for single process communicators,
13   MatSeqSELLSetPreallocation is supported, and similarly MatMPISELLSetPreallocation is supported
14   for communicators controlling multiple processes.  It is recommended that you call both of
15   the above preallocation routines for simplicity.
16 
17    Options Database Keys:
18 . -mat_type sell - sets the matrix type to "sell" during a call to MatSetFromOptions()
19 
20   Level: beginner
21 
22 .seealso: MatCreateSELL(), MatCreateSeqSELL(), MATSEQSELL, MATMPISELL
23 M*/
24 
25 PetscErrorCode MatDiagonalSet_MPISELL(Mat Y,Vec D,InsertMode is)
26 {
27   Mat_MPISELL    *sell=(Mat_MPISELL*)Y->data;
28 
29   PetscFunctionBegin;
30   if (Y->assembled && Y->rmap->rstart == Y->cmap->rstart && Y->rmap->rend == Y->cmap->rend) {
31     CHKERRQ(MatDiagonalSet(sell->A,D,is));
32   } else {
33     CHKERRQ(MatDiagonalSet_Default(Y,D,is));
34   }
35   PetscFunctionReturn(0);
36 }
37 
38 /*
39   Local utility routine that creates a mapping from the global column
40 number to the local number in the off-diagonal part of the local
41 storage of the matrix.  When PETSC_USE_CTABLE is used this is scalable at
42 a slightly higher hash table cost; without it it is not scalable (each processor
43 has an order N integer array but is fast to acess.
44 */
45 PetscErrorCode MatCreateColmap_MPISELL_Private(Mat mat)
46 {
47   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
48   PetscInt       n=sell->B->cmap->n,i;
49 
50   PetscFunctionBegin;
51   PetscCheck(sell->garray,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MPISELL Matrix was assembled but is missing garray");
52 #if defined(PETSC_USE_CTABLE)
53   CHKERRQ(PetscTableCreate(n,mat->cmap->N+1,&sell->colmap));
54   for (i=0; i<n; i++) {
55     CHKERRQ(PetscTableAdd(sell->colmap,sell->garray[i]+1,i+1,INSERT_VALUES));
56   }
57 #else
58   CHKERRQ(PetscCalloc1(mat->cmap->N+1,&sell->colmap));
59   CHKERRQ(PetscLogObjectMemory((PetscObject)mat,(mat->cmap->N+1)*sizeof(PetscInt)));
60   for (i=0; i<n; i++) sell->colmap[sell->garray[i]] = i+1;
61 #endif
62   PetscFunctionReturn(0);
63 }
64 
65 #define MatSetValues_SeqSELL_A_Private(row,col,value,addv,orow,ocol) \
66   { \
67     if (col <= lastcol1) low1 = 0; \
68     else                high1 = nrow1; \
69     lastcol1 = col; \
70     while (high1-low1 > 5) { \
71       t = (low1+high1)/2; \
72       if (*(cp1+8*t) > col) high1 = t; \
73       else                   low1 = t; \
74     } \
75     for (_i=low1; _i<high1; _i++) { \
76       if (*(cp1+8*_i) > col) break; \
77       if (*(cp1+8*_i) == col) { \
78         if (addv == ADD_VALUES) *(vp1+8*_i) += value;   \
79         else                     *(vp1+8*_i) = value; \
80         goto a_noinsert; \
81       } \
82     }  \
83     if (value == 0.0 && ignorezeroentries) {low1 = 0; high1 = nrow1;goto a_noinsert;} \
84     if (nonew == 1) {low1 = 0; high1 = nrow1; goto a_noinsert;} \
85     PetscCheckFalse(nonew == -1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at global row/column (%" PetscInt_FMT ", %" PetscInt_FMT ") into matrix", orow, ocol); \
86     MatSeqXSELLReallocateSELL(A,am,1,nrow1,a->sliidx,row/8,row,col,a->colidx,a->val,cp1,vp1,nonew,MatScalar); \
87     /* shift up all the later entries in this row */ \
88     for (ii=nrow1-1; ii>=_i; ii--) { \
89       *(cp1+8*(ii+1)) = *(cp1+8*ii); \
90       *(vp1+8*(ii+1)) = *(vp1+8*ii); \
91     } \
92     *(cp1+8*_i) = col; \
93     *(vp1+8*_i) = value; \
94     a->nz++; nrow1++; A->nonzerostate++; \
95     a_noinsert: ; \
96     a->rlen[row] = nrow1; \
97   }
98 
99 #define MatSetValues_SeqSELL_B_Private(row,col,value,addv,orow,ocol) \
100   { \
101     if (col <= lastcol2) low2 = 0; \
102     else                high2 = nrow2; \
103     lastcol2 = col; \
104     while (high2-low2 > 5) { \
105       t = (low2+high2)/2; \
106       if (*(cp2+8*t) > col) high2 = t; \
107       else low2  = t; \
108     } \
109     for (_i=low2; _i<high2; _i++) { \
110       if (*(cp2+8*_i) > col) break; \
111       if (*(cp2+8*_i) == col) { \
112         if (addv == ADD_VALUES) *(vp2+8*_i) += value; \
113         else                     *(vp2+8*_i) = value; \
114         goto b_noinsert; \
115       } \
116     } \
117     if (value == 0.0 && ignorezeroentries) {low2 = 0; high2 = nrow2; goto b_noinsert;} \
118     if (nonew == 1) {low2 = 0; high2 = nrow2; goto b_noinsert;} \
119     PetscCheckFalse(nonew == -1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at global row/column (%" PetscInt_FMT ", %" PetscInt_FMT ") into matrix", orow, ocol); \
120     MatSeqXSELLReallocateSELL(B,bm,1,nrow2,b->sliidx,row/8,row,col,b->colidx,b->val,cp2,vp2,nonew,MatScalar); \
121     /* shift up all the later entries in this row */ \
122     for (ii=nrow2-1; ii>=_i; ii--) { \
123       *(cp2+8*(ii+1)) = *(cp2+8*ii); \
124       *(vp2+8*(ii+1)) = *(vp2+8*ii); \
125     } \
126     *(cp2+8*_i) = col; \
127     *(vp2+8*_i) = value; \
128     b->nz++; nrow2++; B->nonzerostate++; \
129     b_noinsert: ; \
130     b->rlen[row] = nrow2; \
131   }
132 
133 PetscErrorCode MatSetValues_MPISELL(Mat mat,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode addv)
134 {
135   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
136   PetscScalar    value;
137   PetscInt       i,j,rstart=mat->rmap->rstart,rend=mat->rmap->rend,shift1,shift2;
138   PetscInt       cstart=mat->cmap->rstart,cend=mat->cmap->rend,row,col;
139   PetscBool      roworiented=sell->roworiented;
140 
141   /* Some Variables required in the macro */
142   Mat            A=sell->A;
143   Mat_SeqSELL    *a=(Mat_SeqSELL*)A->data;
144   PetscBool      ignorezeroentries=a->ignorezeroentries,found;
145   Mat            B=sell->B;
146   Mat_SeqSELL    *b=(Mat_SeqSELL*)B->data;
147   PetscInt       *cp1,*cp2,ii,_i,nrow1,nrow2,low1,high1,low2,high2,t,lastcol1,lastcol2;
148   MatScalar      *vp1,*vp2;
149 
150   PetscFunctionBegin;
151   for (i=0; i<m; i++) {
152     if (im[i] < 0) continue;
153     PetscCheck(im[i] < mat->rmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT,im[i],mat->rmap->N-1);
154     if (im[i] >= rstart && im[i] < rend) {
155       row      = im[i] - rstart;
156       lastcol1 = -1;
157       shift1   = a->sliidx[row>>3]+(row&0x07); /* starting index of the row */
158       cp1      = a->colidx+shift1;
159       vp1      = a->val+shift1;
160       nrow1    = a->rlen[row];
161       low1     = 0;
162       high1    = nrow1;
163       lastcol2 = -1;
164       shift2   = b->sliidx[row>>3]+(row&0x07); /* starting index of the row */
165       cp2      = b->colidx+shift2;
166       vp2      = b->val+shift2;
167       nrow2    = b->rlen[row];
168       low2     = 0;
169       high2    = nrow2;
170 
171       for (j=0; j<n; j++) {
172         if (roworiented) value = v[i*n+j];
173         else             value = v[i+j*m];
174         if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue;
175         if (in[j] >= cstart && in[j] < cend) {
176           col   = in[j] - cstart;
177           MatSetValue_SeqSELL_Private(A,row,col,value,addv,im[i],in[j],cp1,vp1,lastcol1,low1,high1); /* set one value */
178         } else if (in[j] < 0) continue;
179         else PetscCheck(in[j] < mat->cmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT,in[j],mat->cmap->N-1);
180         else {
181           if (mat->was_assembled) {
182             if (!sell->colmap) {
183               CHKERRQ(MatCreateColmap_MPISELL_Private(mat));
184             }
185 #if defined(PETSC_USE_CTABLE)
186             CHKERRQ(PetscTableFind(sell->colmap,in[j]+1,&col));
187             col--;
188 #else
189             col = sell->colmap[in[j]] - 1;
190 #endif
191             if (col < 0 && !((Mat_SeqSELL*)(sell->B->data))->nonew) {
192               CHKERRQ(MatDisAssemble_MPISELL(mat));
193               col    = in[j];
194               /* Reinitialize the variables required by MatSetValues_SeqSELL_B_Private() */
195               B      = sell->B;
196               b      = (Mat_SeqSELL*)B->data;
197               shift2 = b->sliidx[row>>3]+(row&0x07); /* starting index of the row */
198               cp2    = b->colidx+shift2;
199               vp2    = b->val+shift2;
200               nrow2  = b->rlen[row];
201               low2   = 0;
202               high2  = nrow2;
203             } else PetscCheckFalse(col < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at global row/column (%" PetscInt_FMT ", %" PetscInt_FMT ") into matrix", im[i], in[j]);
204           } else col = in[j];
205           MatSetValue_SeqSELL_Private(B,row,col,value,addv,im[i],in[j],cp2,vp2,lastcol2,low2,high2); /* set one value */
206         }
207       }
208     } else {
209       PetscCheck(!mat->nooffprocentries,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Setting off process row %" PetscInt_FMT " even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set",im[i]);
210       if (!sell->donotstash) {
211         mat->assembled = PETSC_FALSE;
212         if (roworiented) {
213           CHKERRQ(MatStashValuesRow_Private(&mat->stash,im[i],n,in,v+i*n,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES))));
214         } else {
215           CHKERRQ(MatStashValuesCol_Private(&mat->stash,im[i],n,in,v+i,m,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES))));
216         }
217       }
218     }
219   }
220   PetscFunctionReturn(0);
221 }
222 
223 PetscErrorCode MatGetValues_MPISELL(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
224 {
225   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
226   PetscInt       i,j,rstart=mat->rmap->rstart,rend=mat->rmap->rend;
227   PetscInt       cstart=mat->cmap->rstart,cend=mat->cmap->rend,row,col;
228 
229   PetscFunctionBegin;
230   for (i=0; i<m; i++) {
231     if (idxm[i] < 0) continue; /* negative row */
232     PetscCheck(idxm[i] < mat->rmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT,idxm[i],mat->rmap->N-1);
233     if (idxm[i] >= rstart && idxm[i] < rend) {
234       row = idxm[i] - rstart;
235       for (j=0; j<n; j++) {
236         if (idxn[j] < 0) continue; /* negative column */
237         PetscCheck(idxn[j] < mat->cmap->N,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT,idxn[j],mat->cmap->N-1);
238         if (idxn[j] >= cstart && idxn[j] < cend) {
239           col  = idxn[j] - cstart;
240           CHKERRQ(MatGetValues(sell->A,1,&row,1,&col,v+i*n+j));
241         } else {
242           if (!sell->colmap) {
243             CHKERRQ(MatCreateColmap_MPISELL_Private(mat));
244           }
245 #if defined(PETSC_USE_CTABLE)
246           CHKERRQ(PetscTableFind(sell->colmap,idxn[j]+1,&col));
247           col--;
248 #else
249           col = sell->colmap[idxn[j]] - 1;
250 #endif
251           if ((col < 0) || (sell->garray[col] != idxn[j])) *(v+i*n+j) = 0.0;
252           else {
253             CHKERRQ(MatGetValues(sell->B,1,&row,1,&col,v+i*n+j));
254           }
255         }
256       }
257     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only local values currently supported");
258   }
259   PetscFunctionReturn(0);
260 }
261 
262 extern PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat,Vec,Vec);
263 
264 PetscErrorCode MatAssemblyBegin_MPISELL(Mat mat,MatAssemblyType mode)
265 {
266   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
267   PetscInt       nstash,reallocs;
268 
269   PetscFunctionBegin;
270   if (sell->donotstash || mat->nooffprocentries) PetscFunctionReturn(0);
271 
272   CHKERRQ(MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range));
273   CHKERRQ(MatStashGetInfo_Private(&mat->stash,&nstash,&reallocs));
274   CHKERRQ(PetscInfo(sell->A,"Stash has %" PetscInt_FMT " entries, uses %" PetscInt_FMT " mallocs.\n",nstash,reallocs));
275   PetscFunctionReturn(0);
276 }
277 
278 PetscErrorCode MatAssemblyEnd_MPISELL(Mat mat,MatAssemblyType mode)
279 {
280   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
281   PetscMPIInt    n;
282   PetscInt       i,flg;
283   PetscInt       *row,*col;
284   PetscScalar    *val;
285   PetscBool      other_disassembled;
286   /* do not use 'b = (Mat_SeqSELL*)sell->B->data' as B can be reset in disassembly */
287   PetscFunctionBegin;
288   if (!sell->donotstash && !mat->nooffprocentries) {
289     while (1) {
290       CHKERRQ(MatStashScatterGetMesg_Private(&mat->stash,&n,&row,&col,&val,&flg));
291       if (!flg) break;
292 
293       for (i=0; i<n; i++) { /* assemble one by one */
294         CHKERRQ(MatSetValues_MPISELL(mat,1,row+i,1,col+i,val+i,mat->insertmode));
295       }
296     }
297     CHKERRQ(MatStashScatterEnd_Private(&mat->stash));
298   }
299   CHKERRQ(MatAssemblyBegin(sell->A,mode));
300   CHKERRQ(MatAssemblyEnd(sell->A,mode));
301 
302   /*
303      determine if any processor has disassembled, if so we must
304      also disassemble ourselfs, in order that we may reassemble.
305   */
306   /*
307      if nonzero structure of submatrix B cannot change then we know that
308      no processor disassembled thus we can skip this stuff
309   */
310   if (!((Mat_SeqSELL*)sell->B->data)->nonew) {
311     CHKERRMPI(MPIU_Allreduce(&mat->was_assembled,&other_disassembled,1,MPIU_BOOL,MPI_PROD,PetscObjectComm((PetscObject)mat)));
312     PetscCheckFalse(mat->was_assembled && !other_disassembled,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatDisAssemble not implemented yet");
313   }
314   if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) {
315     CHKERRQ(MatSetUpMultiply_MPISELL(mat));
316   }
317   /*
318   CHKERRQ(MatSetOption(sell->B,MAT_USE_INODES,PETSC_FALSE));
319   */
320   CHKERRQ(MatAssemblyBegin(sell->B,mode));
321   CHKERRQ(MatAssemblyEnd(sell->B,mode));
322   CHKERRQ(PetscFree2(sell->rowvalues,sell->rowindices));
323   sell->rowvalues = NULL;
324   CHKERRQ(VecDestroy(&sell->diag));
325 
326   /* if no new nonzero locations are allowed in matrix then only set the matrix state the first time through */
327   if ((!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) || !((Mat_SeqSELL*)(sell->A->data))->nonew) {
328     PetscObjectState state = sell->A->nonzerostate + sell->B->nonzerostate;
329     CHKERRMPI(MPIU_Allreduce(&state,&mat->nonzerostate,1,MPIU_INT64,MPI_SUM,PetscObjectComm((PetscObject)mat)));
330   }
331   PetscFunctionReturn(0);
332 }
333 
334 PetscErrorCode MatZeroEntries_MPISELL(Mat A)
335 {
336   Mat_MPISELL    *l=(Mat_MPISELL*)A->data;
337 
338   PetscFunctionBegin;
339   CHKERRQ(MatZeroEntries(l->A));
340   CHKERRQ(MatZeroEntries(l->B));
341   PetscFunctionReturn(0);
342 }
343 
344 PetscErrorCode MatMult_MPISELL(Mat A,Vec xx,Vec yy)
345 {
346   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
347   PetscInt       nt;
348 
349   PetscFunctionBegin;
350   CHKERRQ(VecGetLocalSize(xx,&nt));
351   PetscCheckFalse(nt != A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Incompatible partition of A (%" PetscInt_FMT ") and xx (%" PetscInt_FMT ")",A->cmap->n,nt);
352   CHKERRQ(VecScatterBegin(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD));
353   CHKERRQ((*a->A->ops->mult)(a->A,xx,yy));
354   CHKERRQ(VecScatterEnd(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD));
355   CHKERRQ((*a->B->ops->multadd)(a->B,a->lvec,yy,yy));
356   PetscFunctionReturn(0);
357 }
358 
359 PetscErrorCode MatMultDiagonalBlock_MPISELL(Mat A,Vec bb,Vec xx)
360 {
361   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
362 
363   PetscFunctionBegin;
364   CHKERRQ(MatMultDiagonalBlock(a->A,bb,xx));
365   PetscFunctionReturn(0);
366 }
367 
368 PetscErrorCode MatMultAdd_MPISELL(Mat A,Vec xx,Vec yy,Vec zz)
369 {
370   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
371 
372   PetscFunctionBegin;
373   CHKERRQ(VecScatterBegin(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD));
374   CHKERRQ((*a->A->ops->multadd)(a->A,xx,yy,zz));
375   CHKERRQ(VecScatterEnd(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD));
376   CHKERRQ((*a->B->ops->multadd)(a->B,a->lvec,zz,zz));
377   PetscFunctionReturn(0);
378 }
379 
380 PetscErrorCode MatMultTranspose_MPISELL(Mat A,Vec xx,Vec yy)
381 {
382   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
383 
384   PetscFunctionBegin;
385   /* do nondiagonal part */
386   CHKERRQ((*a->B->ops->multtranspose)(a->B,xx,a->lvec));
387   /* do local part */
388   CHKERRQ((*a->A->ops->multtranspose)(a->A,xx,yy));
389   /* add partial results together */
390   CHKERRQ(VecScatterBegin(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE));
391   CHKERRQ(VecScatterEnd(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE));
392   PetscFunctionReturn(0);
393 }
394 
395 PetscErrorCode MatIsTranspose_MPISELL(Mat Amat,Mat Bmat,PetscReal tol,PetscBool *f)
396 {
397   MPI_Comm       comm;
398   Mat_MPISELL    *Asell=(Mat_MPISELL*)Amat->data,*Bsell;
399   Mat            Adia=Asell->A,Bdia,Aoff,Boff,*Aoffs,*Boffs;
400   IS             Me,Notme;
401   PetscInt       M,N,first,last,*notme,i;
402   PetscMPIInt    size;
403 
404   PetscFunctionBegin;
405   /* Easy test: symmetric diagonal block */
406   Bsell = (Mat_MPISELL*)Bmat->data; Bdia = Bsell->A;
407   CHKERRQ(MatIsTranspose(Adia,Bdia,tol,f));
408   if (!*f) PetscFunctionReturn(0);
409   CHKERRQ(PetscObjectGetComm((PetscObject)Amat,&comm));
410   CHKERRMPI(MPI_Comm_size(comm,&size));
411   if (size == 1) PetscFunctionReturn(0);
412 
413   /* Hard test: off-diagonal block. This takes a MatCreateSubMatrix. */
414   CHKERRQ(MatGetSize(Amat,&M,&N));
415   CHKERRQ(MatGetOwnershipRange(Amat,&first,&last));
416   CHKERRQ(PetscMalloc1(N-last+first,&notme));
417   for (i=0; i<first; i++) notme[i] = i;
418   for (i=last; i<M; i++) notme[i-last+first] = i;
419   CHKERRQ(ISCreateGeneral(MPI_COMM_SELF,N-last+first,notme,PETSC_COPY_VALUES,&Notme));
420   CHKERRQ(ISCreateStride(MPI_COMM_SELF,last-first,first,1,&Me));
421   CHKERRQ(MatCreateSubMatrices(Amat,1,&Me,&Notme,MAT_INITIAL_MATRIX,&Aoffs));
422   Aoff = Aoffs[0];
423   CHKERRQ(MatCreateSubMatrices(Bmat,1,&Notme,&Me,MAT_INITIAL_MATRIX,&Boffs));
424   Boff = Boffs[0];
425   CHKERRQ(MatIsTranspose(Aoff,Boff,tol,f));
426   CHKERRQ(MatDestroyMatrices(1,&Aoffs));
427   CHKERRQ(MatDestroyMatrices(1,&Boffs));
428   CHKERRQ(ISDestroy(&Me));
429   CHKERRQ(ISDestroy(&Notme));
430   CHKERRQ(PetscFree(notme));
431   PetscFunctionReturn(0);
432 }
433 
434 PetscErrorCode MatMultTransposeAdd_MPISELL(Mat A,Vec xx,Vec yy,Vec zz)
435 {
436   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
437 
438   PetscFunctionBegin;
439   /* do nondiagonal part */
440   CHKERRQ((*a->B->ops->multtranspose)(a->B,xx,a->lvec));
441   /* do local part */
442   CHKERRQ((*a->A->ops->multtransposeadd)(a->A,xx,yy,zz));
443   /* add partial results together */
444   CHKERRQ(VecScatterBegin(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE));
445   CHKERRQ(VecScatterEnd(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE));
446   PetscFunctionReturn(0);
447 }
448 
449 /*
450   This only works correctly for square matrices where the subblock A->A is the
451    diagonal block
452 */
453 PetscErrorCode MatGetDiagonal_MPISELL(Mat A,Vec v)
454 {
455   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
456 
457   PetscFunctionBegin;
458   PetscCheckFalse(A->rmap->N != A->cmap->N,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Supports only square matrix where A->A is diag block");
459   PetscCheckFalse(A->rmap->rstart != A->cmap->rstart || A->rmap->rend != A->cmap->rend,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"row partition must equal col partition");
460   CHKERRQ(MatGetDiagonal(a->A,v));
461   PetscFunctionReturn(0);
462 }
463 
464 PetscErrorCode MatScale_MPISELL(Mat A,PetscScalar aa)
465 {
466   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
467 
468   PetscFunctionBegin;
469   CHKERRQ(MatScale(a->A,aa));
470   CHKERRQ(MatScale(a->B,aa));
471   PetscFunctionReturn(0);
472 }
473 
474 PetscErrorCode MatDestroy_MPISELL(Mat mat)
475 {
476   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
477 
478   PetscFunctionBegin;
479 #if defined(PETSC_USE_LOG)
480   PetscLogObjectState((PetscObject)mat,"Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT,mat->rmap->N,mat->cmap->N);
481 #endif
482   CHKERRQ(MatStashDestroy_Private(&mat->stash));
483   CHKERRQ(VecDestroy(&sell->diag));
484   CHKERRQ(MatDestroy(&sell->A));
485   CHKERRQ(MatDestroy(&sell->B));
486 #if defined(PETSC_USE_CTABLE)
487   CHKERRQ(PetscTableDestroy(&sell->colmap));
488 #else
489   CHKERRQ(PetscFree(sell->colmap));
490 #endif
491   CHKERRQ(PetscFree(sell->garray));
492   CHKERRQ(VecDestroy(&sell->lvec));
493   CHKERRQ(VecScatterDestroy(&sell->Mvctx));
494   CHKERRQ(PetscFree2(sell->rowvalues,sell->rowindices));
495   CHKERRQ(PetscFree(sell->ld));
496   CHKERRQ(PetscFree(mat->data));
497 
498   CHKERRQ(PetscObjectChangeTypeName((PetscObject)mat,NULL));
499   CHKERRQ(PetscObjectComposeFunction((PetscObject)mat,"MatStoreValues_C",NULL));
500   CHKERRQ(PetscObjectComposeFunction((PetscObject)mat,"MatRetrieveValues_C",NULL));
501   CHKERRQ(PetscObjectComposeFunction((PetscObject)mat,"MatIsTranspose_C",NULL));
502   CHKERRQ(PetscObjectComposeFunction((PetscObject)mat,"MatMPISELLSetPreallocation_C",NULL));
503   CHKERRQ(PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpisell_mpiaij_C",NULL));
504   CHKERRQ(PetscObjectComposeFunction((PetscObject)mat,"MatDiagonalScaleLocal_C",NULL));
505   PetscFunctionReturn(0);
506 }
507 
508 #include <petscdraw.h>
509 PetscErrorCode MatView_MPISELL_ASCIIorDraworSocket(Mat mat,PetscViewer viewer)
510 {
511   Mat_MPISELL       *sell=(Mat_MPISELL*)mat->data;
512   PetscErrorCode    ierr;
513   PetscMPIInt       rank=sell->rank,size=sell->size;
514   PetscBool         isdraw,iascii,isbinary;
515   PetscViewer       sviewer;
516   PetscViewerFormat format;
517 
518   PetscFunctionBegin;
519   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw));
520   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
521   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary));
522   if (iascii) {
523     CHKERRQ(PetscViewerGetFormat(viewer,&format));
524     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
525       MatInfo   info;
526       PetscInt *inodes;
527 
528       CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank));
529       CHKERRQ(MatGetInfo(mat,MAT_LOCAL,&info));
530       CHKERRQ(MatInodeGetInodeSizes(sell->A,NULL,&inodes,NULL));
531       CHKERRQ(PetscViewerASCIIPushSynchronized(viewer));
532       if (!inodes) {
533         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %" PetscInt_FMT " nz %" PetscInt_FMT " nz alloced %" PetscInt_FMT " mem %" PetscInt_FMT ", not using I-node routines\n",
534                                                   rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr);
535       } else {
536         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %" PetscInt_FMT " nz %" PetscInt_FMT " nz alloced %" PetscInt_FMT " mem %" PetscInt_FMT ", using I-node routines\n",
537                                                   rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr);
538       }
539       CHKERRQ(MatGetInfo(sell->A,MAT_LOCAL,&info));
540       CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer,"[%d] on-diagonal part: nz %" PetscInt_FMT " \n",rank,(PetscInt)info.nz_used));
541       CHKERRQ(MatGetInfo(sell->B,MAT_LOCAL,&info));
542       CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer,"[%d] off-diagonal part: nz %" PetscInt_FMT " \n",rank,(PetscInt)info.nz_used));
543       CHKERRQ(PetscViewerFlush(viewer));
544       CHKERRQ(PetscViewerASCIIPopSynchronized(viewer));
545       CHKERRQ(PetscViewerASCIIPrintf(viewer,"Information on VecScatter used in matrix-vector product: \n"));
546       CHKERRQ(VecScatterView(sell->Mvctx,viewer));
547       PetscFunctionReturn(0);
548     } else if (format == PETSC_VIEWER_ASCII_INFO) {
549       PetscInt inodecount,inodelimit,*inodes;
550       CHKERRQ(MatInodeGetInodeSizes(sell->A,&inodecount,&inodes,&inodelimit));
551       if (inodes) {
552         CHKERRQ(PetscViewerASCIIPrintf(viewer,"using I-node (on process 0) routines: found %" PetscInt_FMT " nodes, limit used is %" PetscInt_FMT "\n",inodecount,inodelimit));
553       } else {
554         CHKERRQ(PetscViewerASCIIPrintf(viewer,"not using I-node (on process 0) routines\n"));
555       }
556       PetscFunctionReturn(0);
557     } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
558       PetscFunctionReturn(0);
559     }
560   } else if (isbinary) {
561     if (size == 1) {
562       CHKERRQ(PetscObjectSetName((PetscObject)sell->A,((PetscObject)mat)->name));
563       CHKERRQ(MatView(sell->A,viewer));
564     } else {
565       /* CHKERRQ(MatView_MPISELL_Binary(mat,viewer)); */
566     }
567     PetscFunctionReturn(0);
568   } else if (isdraw) {
569     PetscDraw draw;
570     PetscBool isnull;
571     CHKERRQ(PetscViewerDrawGetDraw(viewer,0,&draw));
572     CHKERRQ(PetscDrawIsNull(draw,&isnull));
573     if (isnull) PetscFunctionReturn(0);
574   }
575 
576   {
577     /* assemble the entire matrix onto first processor. */
578     Mat         A;
579     Mat_SeqSELL *Aloc;
580     PetscInt    M=mat->rmap->N,N=mat->cmap->N,*acolidx,row,col,i,j;
581     MatScalar   *aval;
582     PetscBool   isnonzero;
583 
584     CHKERRQ(MatCreate(PetscObjectComm((PetscObject)mat),&A));
585     if (rank == 0) {
586       CHKERRQ(MatSetSizes(A,M,N,M,N));
587     } else {
588       CHKERRQ(MatSetSizes(A,0,0,M,N));
589     }
590     /* This is just a temporary matrix, so explicitly using MATMPISELL is probably best */
591     CHKERRQ(MatSetType(A,MATMPISELL));
592     CHKERRQ(MatMPISELLSetPreallocation(A,0,NULL,0,NULL));
593     CHKERRQ(MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE));
594     CHKERRQ(PetscLogObjectParent((PetscObject)mat,(PetscObject)A));
595 
596     /* copy over the A part */
597     Aloc = (Mat_SeqSELL*)sell->A->data;
598     acolidx = Aloc->colidx; aval = Aloc->val;
599     for (i=0; i<Aloc->totalslices; i++) { /* loop over slices */
600       for (j=Aloc->sliidx[i]; j<Aloc->sliidx[i+1]; j++) {
601         isnonzero = (PetscBool)((j-Aloc->sliidx[i])/8 < Aloc->rlen[(i<<3)+(j&0x07)]);
602         if (isnonzero) { /* check the mask bit */
603           row  = (i<<3)+(j&0x07) + mat->rmap->rstart; /* i<<3 is the starting row of this slice */
604           col  = *acolidx + mat->rmap->rstart;
605           CHKERRQ(MatSetValues(A,1,&row,1,&col,aval,INSERT_VALUES));
606         }
607         aval++; acolidx++;
608       }
609     }
610 
611     /* copy over the B part */
612     Aloc = (Mat_SeqSELL*)sell->B->data;
613     acolidx = Aloc->colidx; aval = Aloc->val;
614     for (i=0; i<Aloc->totalslices; i++) {
615       for (j=Aloc->sliidx[i]; j<Aloc->sliidx[i+1]; j++) {
616         isnonzero = (PetscBool)((j-Aloc->sliidx[i])/8 < Aloc->rlen[(i<<3)+(j&0x07)]);
617         if (isnonzero) {
618           row  = (i<<3)+(j&0x07) + mat->rmap->rstart;
619           col  = sell->garray[*acolidx];
620           CHKERRQ(MatSetValues(A,1,&row,1,&col,aval,INSERT_VALUES));
621         }
622         aval++; acolidx++;
623       }
624     }
625 
626     CHKERRQ(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
627     CHKERRQ(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
628     /*
629        Everyone has to call to draw the matrix since the graphics waits are
630        synchronized across all processors that share the PetscDraw object
631     */
632     CHKERRQ(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
633     if (rank == 0) {
634       CHKERRQ(PetscObjectSetName((PetscObject)((Mat_MPISELL*)(A->data))->A,((PetscObject)mat)->name));
635       CHKERRQ(MatView_SeqSELL(((Mat_MPISELL*)(A->data))->A,sviewer));
636     }
637     CHKERRQ(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
638     CHKERRQ(PetscViewerFlush(viewer));
639     CHKERRQ(MatDestroy(&A));
640   }
641   PetscFunctionReturn(0);
642 }
643 
644 PetscErrorCode MatView_MPISELL(Mat mat,PetscViewer viewer)
645 {
646   PetscBool      iascii,isdraw,issocket,isbinary;
647 
648   PetscFunctionBegin;
649   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
650   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw));
651   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary));
652   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSOCKET,&issocket));
653   if (iascii || isdraw || isbinary || issocket) {
654     CHKERRQ(MatView_MPISELL_ASCIIorDraworSocket(mat,viewer));
655   }
656   PetscFunctionReturn(0);
657 }
658 
659 PetscErrorCode MatGetGhosts_MPISELL(Mat mat,PetscInt *nghosts,const PetscInt *ghosts[])
660 {
661   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
662 
663   PetscFunctionBegin;
664   CHKERRQ(MatGetSize(sell->B,NULL,nghosts));
665   if (ghosts) *ghosts = sell->garray;
666   PetscFunctionReturn(0);
667 }
668 
669 PetscErrorCode MatGetInfo_MPISELL(Mat matin,MatInfoType flag,MatInfo *info)
670 {
671   Mat_MPISELL    *mat=(Mat_MPISELL*)matin->data;
672   Mat            A=mat->A,B=mat->B;
673   PetscLogDouble isend[5],irecv[5];
674 
675   PetscFunctionBegin;
676   info->block_size = 1.0;
677   CHKERRQ(MatGetInfo(A,MAT_LOCAL,info));
678 
679   isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded;
680   isend[3] = info->memory;  isend[4] = info->mallocs;
681 
682   CHKERRQ(MatGetInfo(B,MAT_LOCAL,info));
683 
684   isend[0] += info->nz_used; isend[1] += info->nz_allocated; isend[2] += info->nz_unneeded;
685   isend[3] += info->memory;  isend[4] += info->mallocs;
686   if (flag == MAT_LOCAL) {
687     info->nz_used      = isend[0];
688     info->nz_allocated = isend[1];
689     info->nz_unneeded  = isend[2];
690     info->memory       = isend[3];
691     info->mallocs      = isend[4];
692   } else if (flag == MAT_GLOBAL_MAX) {
693     CHKERRMPI(MPIU_Allreduce(isend,irecv,5,MPIU_PETSCLOGDOUBLE,MPI_MAX,PetscObjectComm((PetscObject)matin)));
694 
695     info->nz_used      = irecv[0];
696     info->nz_allocated = irecv[1];
697     info->nz_unneeded  = irecv[2];
698     info->memory       = irecv[3];
699     info->mallocs      = irecv[4];
700   } else if (flag == MAT_GLOBAL_SUM) {
701     CHKERRMPI(MPIU_Allreduce(isend,irecv,5,MPIU_PETSCLOGDOUBLE,MPI_SUM,PetscObjectComm((PetscObject)matin)));
702 
703     info->nz_used      = irecv[0];
704     info->nz_allocated = irecv[1];
705     info->nz_unneeded  = irecv[2];
706     info->memory       = irecv[3];
707     info->mallocs      = irecv[4];
708   }
709   info->fill_ratio_given  = 0; /* no parallel LU/ILU/Cholesky */
710   info->fill_ratio_needed = 0;
711   info->factor_mallocs    = 0;
712   PetscFunctionReturn(0);
713 }
714 
715 PetscErrorCode MatSetOption_MPISELL(Mat A,MatOption op,PetscBool flg)
716 {
717   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
718 
719   PetscFunctionBegin;
720   switch (op) {
721   case MAT_NEW_NONZERO_LOCATIONS:
722   case MAT_NEW_NONZERO_ALLOCATION_ERR:
723   case MAT_UNUSED_NONZERO_LOCATION_ERR:
724   case MAT_KEEP_NONZERO_PATTERN:
725   case MAT_NEW_NONZERO_LOCATION_ERR:
726   case MAT_USE_INODES:
727   case MAT_IGNORE_ZERO_ENTRIES:
728     MatCheckPreallocated(A,1);
729     CHKERRQ(MatSetOption(a->A,op,flg));
730     CHKERRQ(MatSetOption(a->B,op,flg));
731     break;
732   case MAT_ROW_ORIENTED:
733     MatCheckPreallocated(A,1);
734     a->roworiented = flg;
735 
736     CHKERRQ(MatSetOption(a->A,op,flg));
737     CHKERRQ(MatSetOption(a->B,op,flg));
738     break;
739   case MAT_FORCE_DIAGONAL_ENTRIES:
740   case MAT_SORTED_FULL:
741     CHKERRQ(PetscInfo(A,"Option %s ignored\n",MatOptions[op]));
742     break;
743   case MAT_IGNORE_OFF_PROC_ENTRIES:
744     a->donotstash = flg;
745     break;
746   case MAT_SPD:
747     A->spd_set = PETSC_TRUE;
748     A->spd     = flg;
749     if (flg) {
750       A->symmetric                  = PETSC_TRUE;
751       A->structurally_symmetric     = PETSC_TRUE;
752       A->symmetric_set              = PETSC_TRUE;
753       A->structurally_symmetric_set = PETSC_TRUE;
754     }
755     break;
756   case MAT_SYMMETRIC:
757     MatCheckPreallocated(A,1);
758     CHKERRQ(MatSetOption(a->A,op,flg));
759     break;
760   case MAT_STRUCTURALLY_SYMMETRIC:
761     MatCheckPreallocated(A,1);
762     CHKERRQ(MatSetOption(a->A,op,flg));
763     break;
764   case MAT_HERMITIAN:
765     MatCheckPreallocated(A,1);
766     CHKERRQ(MatSetOption(a->A,op,flg));
767     break;
768   case MAT_SYMMETRY_ETERNAL:
769     MatCheckPreallocated(A,1);
770     CHKERRQ(MatSetOption(a->A,op,flg));
771     break;
772   default:
773     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
774   }
775   PetscFunctionReturn(0);
776 }
777 
778 PetscErrorCode MatDiagonalScale_MPISELL(Mat mat,Vec ll,Vec rr)
779 {
780   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
781   Mat            a=sell->A,b=sell->B;
782   PetscInt       s1,s2,s3;
783 
784   PetscFunctionBegin;
785   CHKERRQ(MatGetLocalSize(mat,&s2,&s3));
786   if (rr) {
787     CHKERRQ(VecGetLocalSize(rr,&s1));
788     PetscCheckFalse(s1!=s3,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"right vector non-conforming local size");
789     /* Overlap communication with computation. */
790     CHKERRQ(VecScatterBegin(sell->Mvctx,rr,sell->lvec,INSERT_VALUES,SCATTER_FORWARD));
791   }
792   if (ll) {
793     CHKERRQ(VecGetLocalSize(ll,&s1));
794     PetscCheckFalse(s1!=s2,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"left vector non-conforming local size");
795     CHKERRQ((*b->ops->diagonalscale)(b,ll,NULL));
796   }
797   /* scale  the diagonal block */
798   CHKERRQ((*a->ops->diagonalscale)(a,ll,rr));
799 
800   if (rr) {
801     /* Do a scatter end and then right scale the off-diagonal block */
802     CHKERRQ(VecScatterEnd(sell->Mvctx,rr,sell->lvec,INSERT_VALUES,SCATTER_FORWARD));
803     CHKERRQ((*b->ops->diagonalscale)(b,NULL,sell->lvec));
804   }
805   PetscFunctionReturn(0);
806 }
807 
808 PetscErrorCode MatSetUnfactored_MPISELL(Mat A)
809 {
810   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
811 
812   PetscFunctionBegin;
813   CHKERRQ(MatSetUnfactored(a->A));
814   PetscFunctionReturn(0);
815 }
816 
817 PetscErrorCode MatEqual_MPISELL(Mat A,Mat B,PetscBool  *flag)
818 {
819   Mat_MPISELL    *matB=(Mat_MPISELL*)B->data,*matA=(Mat_MPISELL*)A->data;
820   Mat            a,b,c,d;
821   PetscBool      flg;
822 
823   PetscFunctionBegin;
824   a = matA->A; b = matA->B;
825   c = matB->A; d = matB->B;
826 
827   CHKERRQ(MatEqual(a,c,&flg));
828   if (flg) {
829     CHKERRQ(MatEqual(b,d,&flg));
830   }
831   CHKERRMPI(MPIU_Allreduce(&flg,flag,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
832   PetscFunctionReturn(0);
833 }
834 
835 PetscErrorCode MatCopy_MPISELL(Mat A,Mat B,MatStructure str)
836 {
837   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
838   Mat_MPISELL    *b=(Mat_MPISELL*)B->data;
839 
840   PetscFunctionBegin;
841   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
842   if ((str != SAME_NONZERO_PATTERN) || (A->ops->copy != B->ops->copy)) {
843     /* because of the column compression in the off-processor part of the matrix a->B,
844        the number of columns in a->B and b->B may be different, hence we cannot call
845        the MatCopy() directly on the two parts. If need be, we can provide a more
846        efficient copy than the MatCopy_Basic() by first uncompressing the a->B matrices
847        then copying the submatrices */
848     CHKERRQ(MatCopy_Basic(A,B,str));
849   } else {
850     CHKERRQ(MatCopy(a->A,b->A,str));
851     CHKERRQ(MatCopy(a->B,b->B,str));
852   }
853   PetscFunctionReturn(0);
854 }
855 
856 PetscErrorCode MatSetUp_MPISELL(Mat A)
857 {
858   PetscFunctionBegin;
859   CHKERRQ(MatMPISELLSetPreallocation(A,PETSC_DEFAULT,NULL,PETSC_DEFAULT,NULL));
860   PetscFunctionReturn(0);
861 }
862 
863 extern PetscErrorCode MatConjugate_SeqSELL(Mat);
864 
865 PetscErrorCode MatConjugate_MPISELL(Mat mat)
866 {
867   PetscFunctionBegin;
868   if (PetscDefined(USE_COMPLEX)) {
869     Mat_MPISELL *sell=(Mat_MPISELL*)mat->data;
870 
871     CHKERRQ(MatConjugate_SeqSELL(sell->A));
872     CHKERRQ(MatConjugate_SeqSELL(sell->B));
873   }
874   PetscFunctionReturn(0);
875 }
876 
877 PetscErrorCode MatRealPart_MPISELL(Mat A)
878 {
879   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
880 
881   PetscFunctionBegin;
882   CHKERRQ(MatRealPart(a->A));
883   CHKERRQ(MatRealPart(a->B));
884   PetscFunctionReturn(0);
885 }
886 
887 PetscErrorCode MatImaginaryPart_MPISELL(Mat A)
888 {
889   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
890 
891   PetscFunctionBegin;
892   CHKERRQ(MatImaginaryPart(a->A));
893   CHKERRQ(MatImaginaryPart(a->B));
894   PetscFunctionReturn(0);
895 }
896 
897 PetscErrorCode MatInvertBlockDiagonal_MPISELL(Mat A,const PetscScalar **values)
898 {
899   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
900 
901   PetscFunctionBegin;
902   CHKERRQ(MatInvertBlockDiagonal(a->A,values));
903   A->factorerrortype = a->A->factorerrortype;
904   PetscFunctionReturn(0);
905 }
906 
907 static PetscErrorCode MatSetRandom_MPISELL(Mat x,PetscRandom rctx)
908 {
909   Mat_MPISELL    *sell=(Mat_MPISELL*)x->data;
910 
911   PetscFunctionBegin;
912   CHKERRQ(MatSetRandom(sell->A,rctx));
913   CHKERRQ(MatSetRandom(sell->B,rctx));
914   CHKERRQ(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY));
915   CHKERRQ(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY));
916   PetscFunctionReturn(0);
917 }
918 
919 PetscErrorCode MatSetFromOptions_MPISELL(PetscOptionItems *PetscOptionsObject,Mat A)
920 {
921   PetscFunctionBegin;
922   CHKERRQ(PetscOptionsHead(PetscOptionsObject,"MPISELL options"));
923   CHKERRQ(PetscOptionsTail());
924   PetscFunctionReturn(0);
925 }
926 
927 PetscErrorCode MatShift_MPISELL(Mat Y,PetscScalar a)
928 {
929   Mat_MPISELL    *msell=(Mat_MPISELL*)Y->data;
930   Mat_SeqSELL    *sell=(Mat_SeqSELL*)msell->A->data;
931 
932   PetscFunctionBegin;
933   if (!Y->preallocated) {
934     CHKERRQ(MatMPISELLSetPreallocation(Y,1,NULL,0,NULL));
935   } else if (!sell->nz) {
936     PetscInt nonew = sell->nonew;
937     CHKERRQ(MatSeqSELLSetPreallocation(msell->A,1,NULL));
938     sell->nonew = nonew;
939   }
940   CHKERRQ(MatShift_Basic(Y,a));
941   PetscFunctionReturn(0);
942 }
943 
944 PetscErrorCode MatMissingDiagonal_MPISELL(Mat A,PetscBool  *missing,PetscInt *d)
945 {
946   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
947 
948   PetscFunctionBegin;
949   PetscCheckFalse(A->rmap->n != A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only works for square matrices");
950   CHKERRQ(MatMissingDiagonal(a->A,missing,d));
951   if (d) {
952     PetscInt rstart;
953     CHKERRQ(MatGetOwnershipRange(A,&rstart,NULL));
954     *d += rstart;
955 
956   }
957   PetscFunctionReturn(0);
958 }
959 
960 PetscErrorCode MatGetDiagonalBlock_MPISELL(Mat A,Mat *a)
961 {
962   PetscFunctionBegin;
963   *a = ((Mat_MPISELL*)A->data)->A;
964   PetscFunctionReturn(0);
965 }
966 
967 /* -------------------------------------------------------------------*/
968 static struct _MatOps MatOps_Values = {MatSetValues_MPISELL,
969                                        NULL,
970                                        NULL,
971                                        MatMult_MPISELL,
972                                 /* 4*/ MatMultAdd_MPISELL,
973                                        MatMultTranspose_MPISELL,
974                                        MatMultTransposeAdd_MPISELL,
975                                        NULL,
976                                        NULL,
977                                        NULL,
978                                 /*10*/ NULL,
979                                        NULL,
980                                        NULL,
981                                        MatSOR_MPISELL,
982                                        NULL,
983                                 /*15*/ MatGetInfo_MPISELL,
984                                        MatEqual_MPISELL,
985                                        MatGetDiagonal_MPISELL,
986                                        MatDiagonalScale_MPISELL,
987                                        NULL,
988                                 /*20*/ MatAssemblyBegin_MPISELL,
989                                        MatAssemblyEnd_MPISELL,
990                                        MatSetOption_MPISELL,
991                                        MatZeroEntries_MPISELL,
992                                 /*24*/ NULL,
993                                        NULL,
994                                        NULL,
995                                        NULL,
996                                        NULL,
997                                 /*29*/ MatSetUp_MPISELL,
998                                        NULL,
999                                        NULL,
1000                                        MatGetDiagonalBlock_MPISELL,
1001                                        NULL,
1002                                 /*34*/ MatDuplicate_MPISELL,
1003                                        NULL,
1004                                        NULL,
1005                                        NULL,
1006                                        NULL,
1007                                 /*39*/ NULL,
1008                                        NULL,
1009                                        NULL,
1010                                        MatGetValues_MPISELL,
1011                                        MatCopy_MPISELL,
1012                                 /*44*/ NULL,
1013                                        MatScale_MPISELL,
1014                                        MatShift_MPISELL,
1015                                        MatDiagonalSet_MPISELL,
1016                                        NULL,
1017                                 /*49*/ MatSetRandom_MPISELL,
1018                                        NULL,
1019                                        NULL,
1020                                        NULL,
1021                                        NULL,
1022                                 /*54*/ MatFDColoringCreate_MPIXAIJ,
1023                                        NULL,
1024                                        MatSetUnfactored_MPISELL,
1025                                        NULL,
1026                                        NULL,
1027                                 /*59*/ NULL,
1028                                        MatDestroy_MPISELL,
1029                                        MatView_MPISELL,
1030                                        NULL,
1031                                        NULL,
1032                                 /*64*/ NULL,
1033                                        NULL,
1034                                        NULL,
1035                                        NULL,
1036                                        NULL,
1037                                 /*69*/ NULL,
1038                                        NULL,
1039                                        NULL,
1040                                        NULL,
1041                                        NULL,
1042                                        NULL,
1043                                 /*75*/ MatFDColoringApply_AIJ, /* reuse AIJ function */
1044                                        MatSetFromOptions_MPISELL,
1045                                        NULL,
1046                                        NULL,
1047                                        NULL,
1048                                 /*80*/ NULL,
1049                                        NULL,
1050                                        NULL,
1051                                 /*83*/ NULL,
1052                                        NULL,
1053                                        NULL,
1054                                        NULL,
1055                                        NULL,
1056                                        NULL,
1057                                 /*89*/ NULL,
1058                                        NULL,
1059                                        NULL,
1060                                        NULL,
1061                                        NULL,
1062                                 /*94*/ NULL,
1063                                        NULL,
1064                                        NULL,
1065                                        NULL,
1066                                        NULL,
1067                                 /*99*/ NULL,
1068                                        NULL,
1069                                        NULL,
1070                                        MatConjugate_MPISELL,
1071                                        NULL,
1072                                 /*104*/NULL,
1073                                        MatRealPart_MPISELL,
1074                                        MatImaginaryPart_MPISELL,
1075                                        NULL,
1076                                        NULL,
1077                                 /*109*/NULL,
1078                                        NULL,
1079                                        NULL,
1080                                        NULL,
1081                                        MatMissingDiagonal_MPISELL,
1082                                 /*114*/NULL,
1083                                        NULL,
1084                                        MatGetGhosts_MPISELL,
1085                                        NULL,
1086                                        NULL,
1087                                 /*119*/NULL,
1088                                        NULL,
1089                                        NULL,
1090                                        NULL,
1091                                        NULL,
1092                                 /*124*/NULL,
1093                                        NULL,
1094                                        MatInvertBlockDiagonal_MPISELL,
1095                                        NULL,
1096                                        NULL,
1097                                 /*129*/NULL,
1098                                        NULL,
1099                                        NULL,
1100                                        NULL,
1101                                        NULL,
1102                                 /*134*/NULL,
1103                                        NULL,
1104                                        NULL,
1105                                        NULL,
1106                                        NULL,
1107                                 /*139*/NULL,
1108                                        NULL,
1109                                        NULL,
1110                                        MatFDColoringSetUp_MPIXAIJ,
1111                                        NULL,
1112                                 /*144*/NULL,
1113                                        NULL,
1114                                        NULL,
1115                                        NULL
1116 };
1117 
1118 /* ----------------------------------------------------------------------------------------*/
1119 
1120 PetscErrorCode MatStoreValues_MPISELL(Mat mat)
1121 {
1122   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
1123 
1124   PetscFunctionBegin;
1125   CHKERRQ(MatStoreValues(sell->A));
1126   CHKERRQ(MatStoreValues(sell->B));
1127   PetscFunctionReturn(0);
1128 }
1129 
1130 PetscErrorCode MatRetrieveValues_MPISELL(Mat mat)
1131 {
1132   Mat_MPISELL    *sell=(Mat_MPISELL*)mat->data;
1133 
1134   PetscFunctionBegin;
1135   CHKERRQ(MatRetrieveValues(sell->A));
1136   CHKERRQ(MatRetrieveValues(sell->B));
1137   PetscFunctionReturn(0);
1138 }
1139 
1140 PetscErrorCode MatMPISELLSetPreallocation_MPISELL(Mat B,PetscInt d_rlenmax,const PetscInt d_rlen[],PetscInt o_rlenmax,const PetscInt o_rlen[])
1141 {
1142   Mat_MPISELL    *b;
1143 
1144   PetscFunctionBegin;
1145   CHKERRQ(PetscLayoutSetUp(B->rmap));
1146   CHKERRQ(PetscLayoutSetUp(B->cmap));
1147   b = (Mat_MPISELL*)B->data;
1148 
1149   if (!B->preallocated) {
1150     /* Explicitly create 2 MATSEQSELL matrices. */
1151     CHKERRQ(MatCreate(PETSC_COMM_SELF,&b->A));
1152     CHKERRQ(MatSetSizes(b->A,B->rmap->n,B->cmap->n,B->rmap->n,B->cmap->n));
1153     CHKERRQ(MatSetBlockSizesFromMats(b->A,B,B));
1154     CHKERRQ(MatSetType(b->A,MATSEQSELL));
1155     CHKERRQ(PetscLogObjectParent((PetscObject)B,(PetscObject)b->A));
1156     CHKERRQ(MatCreate(PETSC_COMM_SELF,&b->B));
1157     CHKERRQ(MatSetSizes(b->B,B->rmap->n,B->cmap->N,B->rmap->n,B->cmap->N));
1158     CHKERRQ(MatSetBlockSizesFromMats(b->B,B,B));
1159     CHKERRQ(MatSetType(b->B,MATSEQSELL));
1160     CHKERRQ(PetscLogObjectParent((PetscObject)B,(PetscObject)b->B));
1161   }
1162 
1163   CHKERRQ(MatSeqSELLSetPreallocation(b->A,d_rlenmax,d_rlen));
1164   CHKERRQ(MatSeqSELLSetPreallocation(b->B,o_rlenmax,o_rlen));
1165   B->preallocated  = PETSC_TRUE;
1166   B->was_assembled = PETSC_FALSE;
1167   /*
1168     critical for MatAssemblyEnd to work.
1169     MatAssemblyBegin checks it to set up was_assembled
1170     and MatAssemblyEnd checks was_assembled to determine whether to build garray
1171   */
1172   B->assembled     = PETSC_FALSE;
1173   PetscFunctionReturn(0);
1174 }
1175 
1176 PetscErrorCode MatDuplicate_MPISELL(Mat matin,MatDuplicateOption cpvalues,Mat *newmat)
1177 {
1178   Mat            mat;
1179   Mat_MPISELL    *a,*oldmat=(Mat_MPISELL*)matin->data;
1180 
1181   PetscFunctionBegin;
1182   *newmat = NULL;
1183   CHKERRQ(MatCreate(PetscObjectComm((PetscObject)matin),&mat));
1184   CHKERRQ(MatSetSizes(mat,matin->rmap->n,matin->cmap->n,matin->rmap->N,matin->cmap->N));
1185   CHKERRQ(MatSetBlockSizesFromMats(mat,matin,matin));
1186   CHKERRQ(MatSetType(mat,((PetscObject)matin)->type_name));
1187   a       = (Mat_MPISELL*)mat->data;
1188 
1189   mat->factortype   = matin->factortype;
1190   mat->assembled    = PETSC_TRUE;
1191   mat->insertmode   = NOT_SET_VALUES;
1192   mat->preallocated = PETSC_TRUE;
1193 
1194   a->size         = oldmat->size;
1195   a->rank         = oldmat->rank;
1196   a->donotstash   = oldmat->donotstash;
1197   a->roworiented  = oldmat->roworiented;
1198   a->rowindices   = NULL;
1199   a->rowvalues    = NULL;
1200   a->getrowactive = PETSC_FALSE;
1201 
1202   CHKERRQ(PetscLayoutReference(matin->rmap,&mat->rmap));
1203   CHKERRQ(PetscLayoutReference(matin->cmap,&mat->cmap));
1204 
1205   if (oldmat->colmap) {
1206 #if defined(PETSC_USE_CTABLE)
1207     CHKERRQ(PetscTableCreateCopy(oldmat->colmap,&a->colmap));
1208 #else
1209     CHKERRQ(PetscMalloc1(mat->cmap->N,&a->colmap));
1210     CHKERRQ(PetscLogObjectMemory((PetscObject)mat,(mat->cmap->N)*sizeof(PetscInt)));
1211     CHKERRQ(PetscArraycpy(a->colmap,oldmat->colmap,mat->cmap->N));
1212 #endif
1213   } else a->colmap = NULL;
1214   if (oldmat->garray) {
1215     PetscInt len;
1216     len  = oldmat->B->cmap->n;
1217     CHKERRQ(PetscMalloc1(len+1,&a->garray));
1218     CHKERRQ(PetscLogObjectMemory((PetscObject)mat,len*sizeof(PetscInt)));
1219     if (len) CHKERRQ(PetscArraycpy(a->garray,oldmat->garray,len));
1220   } else a->garray = NULL;
1221 
1222   CHKERRQ(VecDuplicate(oldmat->lvec,&a->lvec));
1223   CHKERRQ(PetscLogObjectParent((PetscObject)mat,(PetscObject)a->lvec));
1224   CHKERRQ(VecScatterCopy(oldmat->Mvctx,&a->Mvctx));
1225   CHKERRQ(PetscLogObjectParent((PetscObject)mat,(PetscObject)a->Mvctx));
1226   CHKERRQ(MatDuplicate(oldmat->A,cpvalues,&a->A));
1227   CHKERRQ(PetscLogObjectParent((PetscObject)mat,(PetscObject)a->A));
1228   CHKERRQ(MatDuplicate(oldmat->B,cpvalues,&a->B));
1229   CHKERRQ(PetscLogObjectParent((PetscObject)mat,(PetscObject)a->B));
1230   CHKERRQ(PetscFunctionListDuplicate(((PetscObject)matin)->qlist,&((PetscObject)mat)->qlist));
1231   *newmat = mat;
1232   PetscFunctionReturn(0);
1233 }
1234 
1235 /*@C
1236    MatMPISELLSetPreallocation - Preallocates memory for a sparse parallel matrix in sell format.
1237    For good matrix assembly performance the user should preallocate the matrix storage by
1238    setting the parameters d_nz (or d_nnz) and o_nz (or o_nnz).
1239 
1240    Collective
1241 
1242    Input Parameters:
1243 +  B - the matrix
1244 .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1245            (same value is used for all local rows)
1246 .  d_nnz - array containing the number of nonzeros in the various rows of the
1247            DIAGONAL portion of the local submatrix (possibly different for each row)
1248            or NULL (PETSC_NULL_INTEGER in Fortran), if d_nz is used to specify the nonzero structure.
1249            The size of this array is equal to the number of local rows, i.e 'm'.
1250            For matrices that will be factored, you must leave room for (and set)
1251            the diagonal entry even if it is zero.
1252 .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1253            submatrix (same value is used for all local rows).
1254 -  o_nnz - array containing the number of nonzeros in the various rows of the
1255            OFF-DIAGONAL portion of the local submatrix (possibly different for
1256            each row) or NULL (PETSC_NULL_INTEGER in Fortran), if o_nz is used to specify the nonzero
1257            structure. The size of this array is equal to the number
1258            of local rows, i.e 'm'.
1259 
1260    If the *_nnz parameter is given then the *_nz parameter is ignored
1261 
1262    The stored row and column indices begin with zero.
1263 
1264    The parallel matrix is partitioned such that the first m0 rows belong to
1265    process 0, the next m1 rows belong to process 1, the next m2 rows belong
1266    to process 2 etc.. where m0,m1,m2... are the input parameter 'm'.
1267 
1268    The DIAGONAL portion of the local submatrix of a processor can be defined
1269    as the submatrix which is obtained by extraction the part corresponding to
1270    the rows r1-r2 and columns c1-c2 of the global matrix, where r1 is the
1271    first row that belongs to the processor, r2 is the last row belonging to
1272    the this processor, and c1-c2 is range of indices of the local part of a
1273    vector suitable for applying the matrix to.  This is an mxn matrix.  In the
1274    common case of a square matrix, the row and column ranges are the same and
1275    the DIAGONAL part is also square. The remaining portion of the local
1276    submatrix (mxN) constitute the OFF-DIAGONAL portion.
1277 
1278    If o_nnz, d_nnz are specified, then o_nz, and d_nz are ignored.
1279 
1280    You can call MatGetInfo() to get information on how effective the preallocation was;
1281    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
1282    You can also run with the option -info and look for messages with the string
1283    malloc in them to see if additional memory allocation was needed.
1284 
1285    Example usage:
1286 
1287    Consider the following 8x8 matrix with 34 non-zero values, that is
1288    assembled across 3 processors. Lets assume that proc0 owns 3 rows,
1289    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
1290    as follows:
1291 
1292 .vb
1293             1  2  0  |  0  3  0  |  0  4
1294     Proc0   0  5  6  |  7  0  0  |  8  0
1295             9  0 10  | 11  0  0  | 12  0
1296     -------------------------------------
1297            13  0 14  | 15 16 17  |  0  0
1298     Proc1   0 18  0  | 19 20 21  |  0  0
1299             0  0  0  | 22 23  0  | 24  0
1300     -------------------------------------
1301     Proc2  25 26 27  |  0  0 28  | 29  0
1302            30  0  0  | 31 32 33  |  0 34
1303 .ve
1304 
1305    This can be represented as a collection of submatrices as:
1306 
1307 .vb
1308       A B C
1309       D E F
1310       G H I
1311 .ve
1312 
1313    Where the submatrices A,B,C are owned by proc0, D,E,F are
1314    owned by proc1, G,H,I are owned by proc2.
1315 
1316    The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1317    The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1318    The 'M','N' parameters are 8,8, and have the same values on all procs.
1319 
1320    The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are
1321    submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices
1322    corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively.
1323    Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL
1324    part as SeqSELL matrices. for eg: proc1 will store [E] as a SeqSELL
1325    matrix, ans [DF] as another SeqSELL matrix.
1326 
1327    When d_nz, o_nz parameters are specified, d_nz storage elements are
1328    allocated for every row of the local diagonal submatrix, and o_nz
1329    storage locations are allocated for every row of the OFF-DIAGONAL submat.
1330    One way to choose d_nz and o_nz is to use the max nonzerors per local
1331    rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices.
1332    In this case, the values of d_nz,o_nz are:
1333 .vb
1334      proc0 : dnz = 2, o_nz = 2
1335      proc1 : dnz = 3, o_nz = 2
1336      proc2 : dnz = 1, o_nz = 4
1337 .ve
1338    We are allocating m*(d_nz+o_nz) storage locations for every proc. This
1339    translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10
1340    for proc3. i.e we are using 12+15+10=37 storage locations to store
1341    34 values.
1342 
1343    When d_nnz, o_nnz parameters are specified, the storage is specified
1344    for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices.
1345    In the above case the values for d_nnz,o_nnz are:
1346 .vb
1347      proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2]
1348      proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1]
1349      proc2: d_nnz = [1,1]   and o_nnz = [4,4]
1350 .ve
1351    Here the space allocated is according to nz (or maximum values in the nnz
1352    if nnz is provided) for DIAGONAL and OFF-DIAGONAL submatrices, i.e (2+2+3+2)*3+(1+4)*2=37
1353 
1354    Level: intermediate
1355 
1356 .seealso: MatCreate(), MatCreateSeqSELL(), MatSetValues(), MatCreatesell(),
1357           MATMPISELL, MatGetInfo(), PetscSplitOwnership()
1358 @*/
1359 PetscErrorCode MatMPISELLSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
1360 {
1361   PetscFunctionBegin;
1362   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
1363   PetscValidType(B,1);
1364   CHKERRQ(PetscTryMethod(B,"MatMPISELLSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz)));
1365   PetscFunctionReturn(0);
1366 }
1367 
1368 /*MC
1369    MATMPISELL - MATMPISELL = "mpisell" - A matrix type to be used for MPI sparse matrices,
1370    based on the sliced Ellpack format
1371 
1372    Options Database Keys:
1373 . -mat_type sell - sets the matrix type to "seqsell" during a call to MatSetFromOptions()
1374 
1375    Level: beginner
1376 
1377 .seealso: MatCreateSell(), MATSEQSELL, MATSELL, MATSEQAIJ, MATAIJ, MATMPIAIJ
1378 M*/
1379 
1380 /*@C
1381    MatCreateSELL - Creates a sparse parallel matrix in SELL format.
1382 
1383    Collective
1384 
1385    Input Parameters:
1386 +  comm - MPI communicator
1387 .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
1388            This value should be the same as the local size used in creating the
1389            y vector for the matrix-vector product y = Ax.
1390 .  n - This value should be the same as the local size used in creating the
1391        x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have
1392        calculated if N is given) For square matrices n is almost always m.
1393 .  M - number of global rows (or PETSC_DETERMINE to have calculated if m is given)
1394 .  N - number of global columns (or PETSC_DETERMINE to have calculated if n is given)
1395 .  d_rlenmax - max number of nonzeros per row in DIAGONAL portion of local submatrix
1396                (same value is used for all local rows)
1397 .  d_rlen - array containing the number of nonzeros in the various rows of the
1398             DIAGONAL portion of the local submatrix (possibly different for each row)
1399             or NULL, if d_rlenmax is used to specify the nonzero structure.
1400             The size of this array is equal to the number of local rows, i.e 'm'.
1401 .  o_rlenmax - max number of nonzeros per row in the OFF-DIAGONAL portion of local
1402                submatrix (same value is used for all local rows).
1403 -  o_rlen - array containing the number of nonzeros in the various rows of the
1404             OFF-DIAGONAL portion of the local submatrix (possibly different for
1405             each row) or NULL, if o_rlenmax is used to specify the nonzero
1406             structure. The size of this array is equal to the number
1407             of local rows, i.e 'm'.
1408 
1409    Output Parameter:
1410 .  A - the matrix
1411 
1412    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
1413    MatXXXXSetPreallocation() paradigm instead of this routine directly.
1414    [MatXXXXSetPreallocation() is, for example, MatSeqSELLSetPreallocation]
1415 
1416    Notes:
1417    If the *_rlen parameter is given then the *_rlenmax parameter is ignored
1418 
1419    m,n,M,N parameters specify the size of the matrix, and its partitioning across
1420    processors, while d_rlenmax,d_rlen,o_rlenmax,o_rlen parameters specify the approximate
1421    storage requirements for this matrix.
1422 
1423    If PETSC_DECIDE or  PETSC_DETERMINE is used for a particular argument on one
1424    processor than it must be used on all processors that share the object for
1425    that argument.
1426 
1427    The user MUST specify either the local or global matrix dimensions
1428    (possibly both).
1429 
1430    The parallel matrix is partitioned across processors such that the
1431    first m0 rows belong to process 0, the next m1 rows belong to
1432    process 1, the next m2 rows belong to process 2 etc.. where
1433    m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores
1434    values corresponding to [m x N] submatrix.
1435 
1436    The columns are logically partitioned with the n0 columns belonging
1437    to 0th partition, the next n1 columns belonging to the next
1438    partition etc.. where n0,n1,n2... are the input parameter 'n'.
1439 
1440    The DIAGONAL portion of the local submatrix on any given processor
1441    is the submatrix corresponding to the rows and columns m,n
1442    corresponding to the given processor. i.e diagonal matrix on
1443    process 0 is [m0 x n0], diagonal matrix on process 1 is [m1 x n1]
1444    etc. The remaining portion of the local submatrix [m x (N-n)]
1445    constitute the OFF-DIAGONAL portion. The example below better
1446    illustrates this concept.
1447 
1448    For a square global matrix we define each processor's diagonal portion
1449    to be its local rows and the corresponding columns (a square submatrix);
1450    each processor's off-diagonal portion encompasses the remainder of the
1451    local matrix (a rectangular submatrix).
1452 
1453    If o_rlen, d_rlen are specified, then o_rlenmax, and d_rlenmax are ignored.
1454 
1455    When calling this routine with a single process communicator, a matrix of
1456    type SEQSELL is returned.  If a matrix of type MATMPISELL is desired for this
1457    type of communicator, use the construction mechanism:
1458      MatCreate(...,&A); MatSetType(A,MATMPISELL); MatSetSizes(A, m,n,M,N); MatMPISELLSetPreallocation(A,...);
1459 
1460    Options Database Keys:
1461 -  -mat_sell_oneindex - Internally use indexing starting at 1
1462         rather than 0.  Note that when calling MatSetValues(),
1463         the user still MUST index entries starting at 0!
1464 
1465    Example usage:
1466 
1467    Consider the following 8x8 matrix with 34 non-zero values, that is
1468    assembled across 3 processors. Lets assume that proc0 owns 3 rows,
1469    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
1470    as follows:
1471 
1472 .vb
1473             1  2  0  |  0  3  0  |  0  4
1474     Proc0   0  5  6  |  7  0  0  |  8  0
1475             9  0 10  | 11  0  0  | 12  0
1476     -------------------------------------
1477            13  0 14  | 15 16 17  |  0  0
1478     Proc1   0 18  0  | 19 20 21  |  0  0
1479             0  0  0  | 22 23  0  | 24  0
1480     -------------------------------------
1481     Proc2  25 26 27  |  0  0 28  | 29  0
1482            30  0  0  | 31 32 33  |  0 34
1483 .ve
1484 
1485    This can be represented as a collection of submatrices as:
1486 
1487 .vb
1488       A B C
1489       D E F
1490       G H I
1491 .ve
1492 
1493    Where the submatrices A,B,C are owned by proc0, D,E,F are
1494    owned by proc1, G,H,I are owned by proc2.
1495 
1496    The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1497    The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively.
1498    The 'M','N' parameters are 8,8, and have the same values on all procs.
1499 
1500    The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are
1501    submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices
1502    corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively.
1503    Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL
1504    part as SeqSELL matrices. for eg: proc1 will store [E] as a SeqSELL
1505    matrix, ans [DF] as another SeqSELL matrix.
1506 
1507    When d_rlenmax, o_rlenmax parameters are specified, d_rlenmax storage elements are
1508    allocated for every row of the local diagonal submatrix, and o_rlenmax
1509    storage locations are allocated for every row of the OFF-DIAGONAL submat.
1510    One way to choose d_rlenmax and o_rlenmax is to use the max nonzerors per local
1511    rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices.
1512    In this case, the values of d_rlenmax,o_rlenmax are:
1513 .vb
1514      proc0 : d_rlenmax = 2, o_rlenmax = 2
1515      proc1 : d_rlenmax = 3, o_rlenmax = 2
1516      proc2 : d_rlenmax = 1, o_rlenmax = 4
1517 .ve
1518    We are allocating m*(d_rlenmax+o_rlenmax) storage locations for every proc. This
1519    translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10
1520    for proc3. i.e we are using 12+15+10=37 storage locations to store
1521    34 values.
1522 
1523    When d_rlen, o_rlen parameters are specified, the storage is specified
1524    for every row, corresponding to both DIAGONAL and OFF-DIAGONAL submatrices.
1525    In the above case the values for d_nnz,o_nnz are:
1526 .vb
1527      proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2]
1528      proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1]
1529      proc2: d_nnz = [1,1]   and o_nnz = [4,4]
1530 .ve
1531    Here the space allocated is still 37 though there are 34 nonzeros because
1532    the allocation is always done according to rlenmax.
1533 
1534    Level: intermediate
1535 
1536 .seealso: MatCreate(), MatCreateSeqSELL(), MatSetValues(), MatMPISELLSetPreallocation(), MatMPISELLSetPreallocationSELL(),
1537           MATMPISELL, MatCreateMPISELLWithArrays()
1538 @*/
1539 PetscErrorCode MatCreateSELL(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscInt d_rlenmax,const PetscInt d_rlen[],PetscInt o_rlenmax,const PetscInt o_rlen[],Mat *A)
1540 {
1541   PetscMPIInt    size;
1542 
1543   PetscFunctionBegin;
1544   CHKERRQ(MatCreate(comm,A));
1545   CHKERRQ(MatSetSizes(*A,m,n,M,N));
1546   CHKERRMPI(MPI_Comm_size(comm,&size));
1547   if (size > 1) {
1548     CHKERRQ(MatSetType(*A,MATMPISELL));
1549     CHKERRQ(MatMPISELLSetPreallocation(*A,d_rlenmax,d_rlen,o_rlenmax,o_rlen));
1550   } else {
1551     CHKERRQ(MatSetType(*A,MATSEQSELL));
1552     CHKERRQ(MatSeqSELLSetPreallocation(*A,d_rlenmax,d_rlen));
1553   }
1554   PetscFunctionReturn(0);
1555 }
1556 
1557 PetscErrorCode MatMPISELLGetSeqSELL(Mat A,Mat *Ad,Mat *Ao,const PetscInt *colmap[])
1558 {
1559   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
1560   PetscBool      flg;
1561 
1562   PetscFunctionBegin;
1563   CHKERRQ(PetscObjectTypeCompare((PetscObject)A,MATMPISELL,&flg));
1564   PetscCheck(flg,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"This function requires a MATMPISELL matrix as input");
1565   if (Ad)     *Ad     = a->A;
1566   if (Ao)     *Ao     = a->B;
1567   if (colmap) *colmap = a->garray;
1568   PetscFunctionReturn(0);
1569 }
1570 
1571 /*@C
1572      MatMPISELLGetLocalMatCondensed - Creates a SeqSELL matrix from an MATMPISELL matrix by taking all its local rows and NON-ZERO columns
1573 
1574     Not Collective
1575 
1576    Input Parameters:
1577 +    A - the matrix
1578 .    scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1579 -    row, col - index sets of rows and columns to extract (or NULL)
1580 
1581    Output Parameter:
1582 .    A_loc - the local sequential matrix generated
1583 
1584     Level: developer
1585 
1586 .seealso: MatGetOwnershipRange(), MatMPISELLGetLocalMat()
1587 
1588 @*/
1589 PetscErrorCode MatMPISELLGetLocalMatCondensed(Mat A,MatReuse scall,IS *row,IS *col,Mat *A_loc)
1590 {
1591   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
1592   PetscInt       i,start,end,ncols,nzA,nzB,*cmap,imark,*idx;
1593   IS             isrowa,iscola;
1594   Mat            *aloc;
1595   PetscBool      match;
1596 
1597   PetscFunctionBegin;
1598   CHKERRQ(PetscObjectTypeCompare((PetscObject)A,MATMPISELL,&match));
1599   PetscCheck(match,PetscObjectComm((PetscObject)A), PETSC_ERR_SUP,"Requires MATMPISELL matrix as input");
1600   CHKERRQ(PetscLogEventBegin(MAT_Getlocalmatcondensed,A,0,0,0));
1601   if (!row) {
1602     start = A->rmap->rstart; end = A->rmap->rend;
1603     CHKERRQ(ISCreateStride(PETSC_COMM_SELF,end-start,start,1,&isrowa));
1604   } else {
1605     isrowa = *row;
1606   }
1607   if (!col) {
1608     start = A->cmap->rstart;
1609     cmap  = a->garray;
1610     nzA   = a->A->cmap->n;
1611     nzB   = a->B->cmap->n;
1612     CHKERRQ(PetscMalloc1(nzA+nzB, &idx));
1613     ncols = 0;
1614     for (i=0; i<nzB; i++) {
1615       if (cmap[i] < start) idx[ncols++] = cmap[i];
1616       else break;
1617     }
1618     imark = i;
1619     for (i=0; i<nzA; i++) idx[ncols++] = start + i;
1620     for (i=imark; i<nzB; i++) idx[ncols++] = cmap[i];
1621     CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,ncols,idx,PETSC_OWN_POINTER,&iscola));
1622   } else {
1623     iscola = *col;
1624   }
1625   if (scall != MAT_INITIAL_MATRIX) {
1626     CHKERRQ(PetscMalloc1(1,&aloc));
1627     aloc[0] = *A_loc;
1628   }
1629   CHKERRQ(MatCreateSubMatrices(A,1,&isrowa,&iscola,scall,&aloc));
1630   *A_loc = aloc[0];
1631   CHKERRQ(PetscFree(aloc));
1632   if (!row) {
1633     CHKERRQ(ISDestroy(&isrowa));
1634   }
1635   if (!col) {
1636     CHKERRQ(ISDestroy(&iscola));
1637   }
1638   CHKERRQ(PetscLogEventEnd(MAT_Getlocalmatcondensed,A,0,0,0));
1639   PetscFunctionReturn(0);
1640 }
1641 
1642 #include <../src/mat/impls/aij/mpi/mpiaij.h>
1643 
1644 PetscErrorCode MatConvert_MPISELL_MPIAIJ(Mat A,MatType newtype,MatReuse reuse,Mat *newmat)
1645 {
1646   Mat_MPISELL    *a=(Mat_MPISELL*)A->data;
1647   Mat            B;
1648   Mat_MPIAIJ     *b;
1649 
1650   PetscFunctionBegin;
1651   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Matrix must be assembled");
1652 
1653   if (reuse == MAT_REUSE_MATRIX) {
1654     B = *newmat;
1655   } else {
1656     CHKERRQ(MatCreate(PetscObjectComm((PetscObject)A),&B));
1657     CHKERRQ(MatSetType(B,MATMPIAIJ));
1658     CHKERRQ(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
1659     CHKERRQ(MatSetBlockSizes(B,A->rmap->bs,A->cmap->bs));
1660     CHKERRQ(MatSeqAIJSetPreallocation(B,0,NULL));
1661     CHKERRQ(MatMPIAIJSetPreallocation(B,0,NULL,0,NULL));
1662   }
1663   b    = (Mat_MPIAIJ*) B->data;
1664 
1665   if (reuse == MAT_REUSE_MATRIX) {
1666     CHKERRQ(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_REUSE_MATRIX, &b->A));
1667     CHKERRQ(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_REUSE_MATRIX, &b->B));
1668   } else {
1669     CHKERRQ(MatDestroy(&b->A));
1670     CHKERRQ(MatDestroy(&b->B));
1671     CHKERRQ(MatDisAssemble_MPISELL(A));
1672     CHKERRQ(MatConvert_SeqSELL_SeqAIJ(a->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->A));
1673     CHKERRQ(MatConvert_SeqSELL_SeqAIJ(a->B, MATSEQAIJ, MAT_INITIAL_MATRIX, &b->B));
1674     CHKERRQ(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
1675     CHKERRQ(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
1676     CHKERRQ(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
1677     CHKERRQ(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
1678   }
1679 
1680   if (reuse == MAT_INPLACE_MATRIX) {
1681     CHKERRQ(MatHeaderReplace(A,&B));
1682   } else {
1683     *newmat = B;
1684   }
1685   PetscFunctionReturn(0);
1686 }
1687 
1688 PetscErrorCode MatConvert_MPIAIJ_MPISELL(Mat A,MatType newtype,MatReuse reuse,Mat *newmat)
1689 {
1690   Mat_MPIAIJ     *a=(Mat_MPIAIJ*)A->data;
1691   Mat            B;
1692   Mat_MPISELL    *b;
1693 
1694   PetscFunctionBegin;
1695   PetscCheck(A->assembled,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Matrix must be assembled");
1696 
1697   if (reuse == MAT_REUSE_MATRIX) {
1698     B = *newmat;
1699   } else {
1700     CHKERRQ(MatCreate(PetscObjectComm((PetscObject)A),&B));
1701     CHKERRQ(MatSetType(B,MATMPISELL));
1702     CHKERRQ(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
1703     CHKERRQ(MatSetBlockSizes(B,A->rmap->bs,A->cmap->bs));
1704     CHKERRQ(MatSeqAIJSetPreallocation(B,0,NULL));
1705     CHKERRQ(MatMPIAIJSetPreallocation(B,0,NULL,0,NULL));
1706   }
1707   b    = (Mat_MPISELL*) B->data;
1708 
1709   if (reuse == MAT_REUSE_MATRIX) {
1710     CHKERRQ(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_REUSE_MATRIX, &b->A));
1711     CHKERRQ(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_REUSE_MATRIX, &b->B));
1712   } else {
1713     CHKERRQ(MatDestroy(&b->A));
1714     CHKERRQ(MatDestroy(&b->B));
1715     CHKERRQ(MatDisAssemble_MPIAIJ(A));
1716     CHKERRQ(MatConvert_SeqAIJ_SeqSELL(a->A, MATSEQSELL, MAT_INITIAL_MATRIX, &b->A));
1717     CHKERRQ(MatConvert_SeqAIJ_SeqSELL(a->B, MATSEQSELL, MAT_INITIAL_MATRIX, &b->B));
1718     CHKERRQ(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
1719     CHKERRQ(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
1720     CHKERRQ(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
1721     CHKERRQ(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
1722   }
1723 
1724   if (reuse == MAT_INPLACE_MATRIX) {
1725     CHKERRQ(MatHeaderReplace(A,&B));
1726   } else {
1727     *newmat = B;
1728   }
1729   PetscFunctionReturn(0);
1730 }
1731 
1732 PetscErrorCode MatSOR_MPISELL(Mat matin,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
1733 {
1734   Mat_MPISELL    *mat=(Mat_MPISELL*)matin->data;
1735   Vec            bb1=NULL;
1736 
1737   PetscFunctionBegin;
1738   if (flag == SOR_APPLY_UPPER) {
1739     CHKERRQ((*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx));
1740     PetscFunctionReturn(0);
1741   }
1742 
1743   if (its > 1 || ~flag & SOR_ZERO_INITIAL_GUESS || flag & SOR_EISENSTAT) {
1744     CHKERRQ(VecDuplicate(bb,&bb1));
1745   }
1746 
1747   if ((flag & SOR_LOCAL_SYMMETRIC_SWEEP) == SOR_LOCAL_SYMMETRIC_SWEEP) {
1748     if (flag & SOR_ZERO_INITIAL_GUESS) {
1749       CHKERRQ((*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx));
1750       its--;
1751     }
1752 
1753     while (its--) {
1754       CHKERRQ(VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD));
1755       CHKERRQ(VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD));
1756 
1757       /* update rhs: bb1 = bb - B*x */
1758       CHKERRQ(VecScale(mat->lvec,-1.0));
1759       CHKERRQ((*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1));
1760 
1761       /* local sweep */
1762       CHKERRQ((*mat->A->ops->sor)(mat->A,bb1,omega,SOR_SYMMETRIC_SWEEP,fshift,lits,1,xx));
1763     }
1764   } else if (flag & SOR_LOCAL_FORWARD_SWEEP) {
1765     if (flag & SOR_ZERO_INITIAL_GUESS) {
1766       CHKERRQ((*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx));
1767       its--;
1768     }
1769     while (its--) {
1770       CHKERRQ(VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD));
1771       CHKERRQ(VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD));
1772 
1773       /* update rhs: bb1 = bb - B*x */
1774       CHKERRQ(VecScale(mat->lvec,-1.0));
1775       CHKERRQ((*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1));
1776 
1777       /* local sweep */
1778       CHKERRQ((*mat->A->ops->sor)(mat->A,bb1,omega,SOR_FORWARD_SWEEP,fshift,lits,1,xx));
1779     }
1780   } else if (flag & SOR_LOCAL_BACKWARD_SWEEP) {
1781     if (flag & SOR_ZERO_INITIAL_GUESS) {
1782       CHKERRQ((*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx));
1783       its--;
1784     }
1785     while (its--) {
1786       CHKERRQ(VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD));
1787       CHKERRQ(VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD));
1788 
1789       /* update rhs: bb1 = bb - B*x */
1790       CHKERRQ(VecScale(mat->lvec,-1.0));
1791       CHKERRQ((*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1));
1792 
1793       /* local sweep */
1794       CHKERRQ((*mat->A->ops->sor)(mat->A,bb1,omega,SOR_BACKWARD_SWEEP,fshift,lits,1,xx));
1795     }
1796   } else SETERRQ(PetscObjectComm((PetscObject)matin),PETSC_ERR_SUP,"Parallel SOR not supported");
1797 
1798   CHKERRQ(VecDestroy(&bb1));
1799 
1800   matin->factorerrortype = mat->A->factorerrortype;
1801   PetscFunctionReturn(0);
1802 }
1803 
1804 /*MC
1805    MATMPISELL - MATMPISELL = "MPISELL" - A matrix type to be used for parallel sparse matrices.
1806 
1807    Options Database Keys:
1808 . -mat_type MPISELL - sets the matrix type to "MPISELL" during a call to MatSetFromOptions()
1809 
1810   Level: beginner
1811 
1812 .seealso: MatCreateSELL()
1813 M*/
1814 PETSC_EXTERN PetscErrorCode MatCreate_MPISELL(Mat B)
1815 {
1816   Mat_MPISELL    *b;
1817   PetscMPIInt    size;
1818 
1819   PetscFunctionBegin;
1820   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B),&size));
1821   CHKERRQ(PetscNewLog(B,&b));
1822   B->data       = (void*)b;
1823   CHKERRQ(PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps)));
1824   B->assembled  = PETSC_FALSE;
1825   B->insertmode = NOT_SET_VALUES;
1826   b->size       = size;
1827   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)B),&b->rank));
1828   /* build cache for off array entries formed */
1829   CHKERRQ(MatStashCreate_Private(PetscObjectComm((PetscObject)B),1,&B->stash));
1830 
1831   b->donotstash  = PETSC_FALSE;
1832   b->colmap      = NULL;
1833   b->garray      = NULL;
1834   b->roworiented = PETSC_TRUE;
1835 
1836   /* stuff used for matrix vector multiply */
1837   b->lvec  = NULL;
1838   b->Mvctx = NULL;
1839 
1840   /* stuff for MatGetRow() */
1841   b->rowindices   = NULL;
1842   b->rowvalues    = NULL;
1843   b->getrowactive = PETSC_FALSE;
1844 
1845   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_MPISELL));
1846   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_MPISELL));
1847   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_MPISELL));
1848   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatMPISELLSetPreallocation_C",MatMPISELLSetPreallocation_MPISELL));
1849   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpisell_mpiaij_C",MatConvert_MPISELL_MPIAIJ));
1850   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatDiagonalScaleLocal_C",MatDiagonalScaleLocal_MPISELL));
1851   CHKERRQ(PetscObjectChangeTypeName((PetscObject)B,MATMPISELL));
1852   PetscFunctionReturn(0);
1853 }
1854