xref: /petsc/src/mat/impls/is/matis.c (revision 55e7fe800d976e85ed2b5cd8bfdef564daa37bd9)
1 /*
2     Creates a matrix class for using the Neumann-Neumann type preconditioners.
3     This stores the matrices in globally unassembled form. Each processor
4     assembles only its local Neumann problem and the parallel matrix vector
5     product is handled "implicitly".
6 
7     Currently this allows for only one subdomain per processor.
8 */
9 
10 #include <../src/mat/impls/is/matis.h>      /*I "petscmat.h" I*/
11 #include <petsc/private/sfimpl.h>
12 
13 #define MATIS_MAX_ENTRIES_INSERTION 2048
14 static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
15 static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
16 static PetscErrorCode MatISSetUpScatters_Private(Mat);
17 
18 static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr)
19 {
20   MatISPtAP      ptap = (MatISPtAP)ptr;
21   PetscErrorCode ierr;
22 
23   PetscFunctionBegin;
24   ierr = MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP);CHKERRQ(ierr);
25   ierr = ISDestroy(&ptap->cis0);CHKERRQ(ierr);
26   ierr = ISDestroy(&ptap->cis1);CHKERRQ(ierr);
27   ierr = ISDestroy(&ptap->ris0);CHKERRQ(ierr);
28   ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
29   ierr = PetscFree(ptap);CHKERRQ(ierr);
30   PetscFunctionReturn(0);
31 }
32 
33 static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C)
34 {
35   MatISPtAP      ptap;
36   Mat_IS         *matis = (Mat_IS*)A->data;
37   Mat            lA,lC;
38   MatReuse       reuse;
39   IS             ris[2],cis[2];
40   PetscContainer c;
41   PetscInt       n;
42   PetscErrorCode ierr;
43 
44   PetscFunctionBegin;
45   ierr = PetscObjectQuery((PetscObject)C,"_MatIS_PtAP",(PetscObject*)&c);CHKERRQ(ierr);
46   if (!c) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information");
47   ierr   = PetscContainerGetPointer(c,(void**)&ptap);CHKERRQ(ierr);
48   ris[0] = ptap->ris0;
49   ris[1] = ptap->ris1;
50   cis[0] = ptap->cis0;
51   cis[1] = ptap->cis1;
52   n      = ptap->ris1 ? 2 : 1;
53   reuse  = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX;
54   ierr   = MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP);CHKERRQ(ierr);
55 
56   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
57   ierr = MatISGetLocalMat(C,&lC);CHKERRQ(ierr);
58   if (ptap->ris1) { /* unsymmetric A mapping */
59     Mat lPt;
60 
61     ierr = MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt);CHKERRQ(ierr);
62     ierr = MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
63     if (matis->storel2l) {
64       ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt);CHKERRQ(ierr);
65     }
66     ierr = MatDestroy(&lPt);CHKERRQ(ierr);
67   } else {
68     ierr = MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
69     if (matis->storel2l) {
70      ierr = PetscObjectCompose((PetscObject)(C),"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0]);CHKERRQ(ierr);
71     }
72   }
73   if (reuse == MAT_INITIAL_MATRIX) {
74     ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
75     ierr = MatDestroy(&lC);CHKERRQ(ierr);
76   }
77   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
78   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
79   PetscFunctionReturn(0);
80 }
81 
82 static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT,IS *cis)
83 {
84   Mat            Po,Pd;
85   IS             zd,zo;
86   const PetscInt *garray;
87   PetscInt       *aux,i,bs;
88   PetscInt       dc,stc,oc,ctd,cto;
89   PetscBool      ismpiaij,ismpibaij,isseqaij,isseqbaij;
90   MPI_Comm       comm;
91   PetscErrorCode ierr;
92 
93   PetscFunctionBegin;
94   PetscValidHeaderSpecific(PT,MAT_CLASSID,1);
95   PetscValidPointer(cis,2);
96   ierr = PetscObjectGetComm((PetscObject)PT,&comm);CHKERRQ(ierr);
97   bs   = 1;
98   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
99   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
100   ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
101   ierr = PetscObjectTypeCompare((PetscObject)PT,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
102   if (isseqaij || isseqbaij) {
103     Pd = PT;
104     Po = NULL;
105     garray = NULL;
106   } else if (ismpiaij) {
107     ierr = MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
108   } else if (ismpibaij) {
109     ierr = MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
110     ierr = MatGetBlockSize(PT,&bs);CHKERRQ(ierr);
111   } else SETERRQ1(comm,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(PT))->type_name);
112 
113   /* identify any null columns in Pd or Po */
114   /* We use a tolerance comparison since it may happen that, with geometric multigrid,
115      some of the columns are not really zero, but very close to */
116   zo = zd = NULL;
117   if (Po) {
118     ierr = MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,PETSC_SMALL,&zo);CHKERRQ(ierr);
119   }
120   ierr = MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,PETSC_SMALL,&zd);CHKERRQ(ierr);
121 
122   ierr = MatGetLocalSize(PT,NULL,&dc);CHKERRQ(ierr);
123   ierr = MatGetOwnershipRangeColumn(PT,&stc,NULL);CHKERRQ(ierr);
124   if (Po) { ierr = MatGetLocalSize(Po,NULL,&oc);CHKERRQ(ierr); }
125   else oc = 0;
126   ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
127   if (zd) {
128     const PetscInt *idxs;
129     PetscInt       nz;
130 
131     /* this will throw an error if bs is not valid */
132     ierr = ISSetBlockSize(zd,bs);CHKERRQ(ierr);
133     ierr = ISGetLocalSize(zd,&nz);CHKERRQ(ierr);
134     ierr = ISGetIndices(zd,&idxs);CHKERRQ(ierr);
135     ctd  = nz/bs;
136     for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs;
137     ierr = ISRestoreIndices(zd,&idxs);CHKERRQ(ierr);
138   } else {
139     ctd = dc/bs;
140     for (i=0; i<ctd; i++) aux[i] = i+stc/bs;
141   }
142   if (zo) {
143     const PetscInt *idxs;
144     PetscInt       nz;
145 
146     /* this will throw an error if bs is not valid */
147     ierr = ISSetBlockSize(zo,bs);CHKERRQ(ierr);
148     ierr = ISGetLocalSize(zo,&nz);CHKERRQ(ierr);
149     ierr = ISGetIndices(zo,&idxs);CHKERRQ(ierr);
150     cto  = nz/bs;
151     for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs];
152     ierr = ISRestoreIndices(zo,&idxs);CHKERRQ(ierr);
153   } else {
154     cto = oc/bs;
155     for (i=0; i<cto; i++) aux[i+ctd] = garray[i];
156   }
157   ierr = ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis);CHKERRQ(ierr);
158   ierr = ISDestroy(&zd);CHKERRQ(ierr);
159   ierr = ISDestroy(&zo);CHKERRQ(ierr);
160   PetscFunctionReturn(0);
161 }
162 
163 static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat *C)
164 {
165   Mat                    PT,lA;
166   MatISPtAP              ptap;
167   ISLocalToGlobalMapping Crl2g,Ccl2g,rl2g,cl2g;
168   PetscContainer         c;
169   MatType                lmtype;
170   const PetscInt         *garray;
171   PetscInt               ibs,N,dc;
172   MPI_Comm               comm;
173   PetscErrorCode         ierr;
174 
175   PetscFunctionBegin;
176   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
177   ierr = MatCreate(comm,C);CHKERRQ(ierr);
178   ierr = MatSetType(*C,MATIS);CHKERRQ(ierr);
179   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
180   ierr = MatGetType(lA,&lmtype);CHKERRQ(ierr);
181   ierr = MatISSetLocalMatType(*C,lmtype);CHKERRQ(ierr);
182   ierr = MatGetSize(P,NULL,&N);CHKERRQ(ierr);
183   ierr = MatGetLocalSize(P,NULL,&dc);CHKERRQ(ierr);
184   ierr = MatSetSizes(*C,dc,dc,N,N);CHKERRQ(ierr);
185 /* Not sure about this
186   ierr = MatGetBlockSizes(P,NULL,&ibs);CHKERRQ(ierr);
187   ierr = MatSetBlockSize(*C,ibs);CHKERRQ(ierr);
188 */
189 
190   ierr = PetscNew(&ptap);CHKERRQ(ierr);
191   ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
192   ierr = PetscContainerSetPointer(c,ptap);CHKERRQ(ierr);
193   ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyPtAP_Private);CHKERRQ(ierr);
194   ierr = PetscObjectCompose((PetscObject)(*C),"_MatIS_PtAP",(PetscObject)c);CHKERRQ(ierr);
195   ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
196   ptap->fill = fill;
197 
198   ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
199 
200   ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&ibs);CHKERRQ(ierr);
201   ierr = ISLocalToGlobalMappingGetSize(cl2g,&N);CHKERRQ(ierr);
202   ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&garray);CHKERRQ(ierr);
203   ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris0);CHKERRQ(ierr);
204   ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&garray);CHKERRQ(ierr);
205 
206   ierr = MatCreateSubMatrix(P,ptap->ris0,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
207   ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis0);CHKERRQ(ierr);
208   ierr = ISLocalToGlobalMappingCreateIS(ptap->cis0,&Ccl2g);CHKERRQ(ierr);
209   ierr = MatDestroy(&PT);CHKERRQ(ierr);
210 
211   Crl2g = NULL;
212   if (rl2g != cl2g) { /* unsymmetric A mapping */
213     PetscBool same,lsame = PETSC_FALSE;
214     PetscInt  N1,ibs1;
215 
216     ierr = ISLocalToGlobalMappingGetSize(rl2g,&N1);CHKERRQ(ierr);
217     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&ibs1);CHKERRQ(ierr);
218     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&garray);CHKERRQ(ierr);
219     ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris1);CHKERRQ(ierr);
220     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&garray);CHKERRQ(ierr);
221     if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */
222       const PetscInt *i1,*i2;
223 
224       ierr = ISBlockGetIndices(ptap->ris0,&i1);CHKERRQ(ierr);
225       ierr = ISBlockGetIndices(ptap->ris1,&i2);CHKERRQ(ierr);
226       ierr = PetscMemcmp(i1,i2,N*sizeof(*i1),&lsame);CHKERRQ(ierr);
227     }
228     ierr = MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm);CHKERRQ(ierr);
229     if (same) {
230       ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
231     } else {
232       ierr = MatCreateSubMatrix(P,ptap->ris1,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
233       ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis1);CHKERRQ(ierr);
234       ierr = ISLocalToGlobalMappingCreateIS(ptap->cis1,&Crl2g);CHKERRQ(ierr);
235       ierr = MatDestroy(&PT);CHKERRQ(ierr);
236     }
237   }
238 /* Not sure about this
239   if (!Crl2g) {
240     ierr = MatGetBlockSize(*C,&ibs);CHKERRQ(ierr);
241     ierr = ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs);CHKERRQ(ierr);
242   }
243 */
244   ierr = MatSetLocalToGlobalMapping(*C,Crl2g ? Crl2g : Ccl2g,Ccl2g);CHKERRQ(ierr);
245   ierr = ISLocalToGlobalMappingDestroy(&Crl2g);CHKERRQ(ierr);
246   ierr = ISLocalToGlobalMappingDestroy(&Ccl2g);CHKERRQ(ierr);
247 
248   (*C)->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ;
249   PetscFunctionReturn(0);
250 }
251 
252 PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
253 {
254   PetscErrorCode ierr;
255 
256   PetscFunctionBegin;
257   if (scall == MAT_INITIAL_MATRIX) {
258     ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
259     ierr = MatPtAPSymbolic_IS_XAIJ(A,P,fill,C);CHKERRQ(ierr);
260     ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
261   }
262   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
263   ierr = ((*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr);
264   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
265   PetscFunctionReturn(0);
266 }
267 
268 static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
269 {
270   MatISLocalFields lf = (MatISLocalFields)ptr;
271   PetscInt         i;
272   PetscErrorCode   ierr;
273 
274   PetscFunctionBegin;
275   for (i=0;i<lf->nr;i++) {
276     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
277   }
278   for (i=0;i<lf->nc;i++) {
279     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
280   }
281   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
282   ierr = PetscFree(lf);CHKERRQ(ierr);
283   PetscFunctionReturn(0);
284 }
285 
286 static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
287 {
288   Mat            B,lB;
289   PetscErrorCode ierr;
290 
291   PetscFunctionBegin;
292   if (reuse != MAT_REUSE_MATRIX) {
293     ISLocalToGlobalMapping rl2g,cl2g;
294     PetscInt               bs;
295     IS                     is;
296 
297     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
298     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->n/bs,0,1,&is);CHKERRQ(ierr);
299     if (bs > 1) {
300       IS       is2;
301       PetscInt i,*aux;
302 
303       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
304       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
305       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
306       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
307       ierr = ISDestroy(&is);CHKERRQ(ierr);
308       is   = is2;
309     }
310     ierr = ISSetIdentity(is);CHKERRQ(ierr);
311     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
312     ierr = ISDestroy(&is);CHKERRQ(ierr);
313     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->n/bs,0,1,&is);CHKERRQ(ierr);
314     if (bs > 1) {
315       IS       is2;
316       PetscInt i,*aux;
317 
318       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
319       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
320       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
321       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
322       ierr = ISDestroy(&is);CHKERRQ(ierr);
323       is   = is2;
324     }
325     ierr = ISSetIdentity(is);CHKERRQ(ierr);
326     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
327     ierr = ISDestroy(&is);CHKERRQ(ierr);
328     ierr = MatCreateIS(PetscObjectComm((PetscObject)A),bs,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,rl2g,cl2g,&B);CHKERRQ(ierr);
329     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
330     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
331     ierr = MatDuplicate(A,MAT_COPY_VALUES,&lB);CHKERRQ(ierr);
332     if (reuse == MAT_INITIAL_MATRIX) *newmat = B;
333   } else {
334     B    = *newmat;
335     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
336     lB   = A;
337   }
338   ierr = MatISSetLocalMat(B,lB);CHKERRQ(ierr);
339   ierr = MatDestroy(&lB);CHKERRQ(ierr);
340   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
341   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
342   if (reuse == MAT_INPLACE_MATRIX) {
343     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
344   }
345   PetscFunctionReturn(0);
346 }
347 
348 static PetscErrorCode MatISScaleDisassembling_Private(Mat A)
349 {
350   Mat_IS         *matis = (Mat_IS*)(A->data);
351   PetscScalar    *aa;
352   const PetscInt *ii,*jj;
353   PetscInt       i,n,m;
354   PetscInt       *ecount,**eneighs;
355   PetscBool      flg;
356   PetscErrorCode ierr;
357 
358   PetscFunctionBegin;
359   ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
360   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
361   ierr = ISLocalToGlobalMappingGetNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
362   if (m != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",m,n);
363   ierr = MatSeqAIJGetArray(matis->A,&aa);CHKERRQ(ierr);
364   for (i=0;i<n;i++) {
365     if (ecount[i] > 1) {
366       PetscInt j;
367 
368       for (j=ii[i];j<ii[i+1];j++) {
369         PetscInt    i2 = jj[j],p,p2;
370         PetscReal   scal = 0.0;
371 
372         for (p=0;p<ecount[i];p++) {
373           for (p2=0;p2<ecount[i2];p2++) {
374             if (eneighs[i][p] == eneighs[i2][p2]) { scal += 1.0; break; }
375           }
376         }
377         if (scal) aa[j] /= scal;
378       }
379     }
380   }
381   ierr = ISLocalToGlobalMappingRestoreNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
382   ierr = MatSeqAIJRestoreArray(matis->A,&aa);CHKERRQ(ierr);
383   ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
384   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
385   PetscFunctionReturn(0);
386 }
387 
388 typedef enum {MAT_IS_DISASSEMBLE_L2G_NATURAL,MAT_IS_DISASSEMBLE_L2G_MAT, MAT_IS_DISASSEMBLE_L2G_ND} MatISDisassemblel2gType;
389 
390 static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g)
391 {
392   Mat                     Ad,Ao;
393   IS                      is,ndmap,ndsub;
394   MPI_Comm                comm;
395   const PetscInt          *garray,*ndmapi;
396   PetscInt                bs,i,cnt,nl,*ncount,*ndmapc;
397   PetscBool               ismpiaij,ismpibaij;
398   const char *const       MatISDisassemblel2gTypes[] = {"NATURAL","MAT","ND","MatISDisassemblel2gType","MAT_IS_DISASSEMBLE_L2G_",0};
399   MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL;
400   MatPartitioning         part;
401   PetscSF                 sf;
402   PetscErrorCode          ierr;
403 
404   PetscFunctionBegin;
405   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat");CHKERRQ(ierr);
406   ierr = PetscOptionsEnum("-mat_is_disassemble_l2g_type","Type of local-to-global mapping to be used for disassembling","MatISDisassemblel2gType",MatISDisassemblel2gTypes,(PetscEnum)mode,(PetscEnum*)&mode,NULL);CHKERRQ(ierr);
407   ierr = PetscOptionsEnd();CHKERRQ(ierr);
408   if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) {
409     ierr = MatGetLocalToGlobalMapping(A,l2g,NULL);CHKERRQ(ierr);
410     PetscFunctionReturn(0);
411   }
412   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
413   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
414   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
415   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
416   switch (mode) {
417   case MAT_IS_DISASSEMBLE_L2G_ND:
418     ierr = MatPartitioningCreate(comm,&part);CHKERRQ(ierr);
419     ierr = MatPartitioningSetAdjacency(part,A);CHKERRQ(ierr);
420     ierr = PetscObjectSetOptionsPrefix((PetscObject)part,((PetscObject)A)->prefix);CHKERRQ(ierr);
421     ierr = MatPartitioningSetFromOptions(part);CHKERRQ(ierr);
422     ierr = MatPartitioningApplyND(part,&ndmap);CHKERRQ(ierr);
423     ierr = MatPartitioningDestroy(&part);CHKERRQ(ierr);
424     ierr = ISBuildTwoSided(ndmap,NULL,&ndsub);CHKERRQ(ierr);
425     ierr = MatMPIAIJSetUseScalableIncreaseOverlap(A,PETSC_TRUE);CHKERRQ(ierr);
426     ierr = MatIncreaseOverlap(A,1,&ndsub,1);CHKERRQ(ierr);
427     ierr = ISLocalToGlobalMappingCreateIS(ndsub,l2g);CHKERRQ(ierr);
428 
429     /* it may happen that a separator node is not properly shared */
430     ierr = ISLocalToGlobalMappingGetNodeInfo(*l2g,&nl,&ncount,NULL);CHKERRQ(ierr);
431     ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr);
432     ierr = ISLocalToGlobalMappingGetIndices(*l2g,&garray);CHKERRQ(ierr);
433     ierr = PetscSFSetGraphLayout(sf,A->rmap,nl,NULL,PETSC_OWN_POINTER,garray);CHKERRQ(ierr);
434     ierr = ISLocalToGlobalMappingRestoreIndices(*l2g,&garray);CHKERRQ(ierr);
435     ierr = PetscCalloc1(A->rmap->n,&ndmapc);CHKERRQ(ierr);
436     ierr = PetscSFReduceBegin(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr);
437     ierr = PetscSFReduceEnd(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr);
438     ierr = ISLocalToGlobalMappingRestoreNodeInfo(*l2g,NULL,&ncount,NULL);CHKERRQ(ierr);
439     ierr = ISGetIndices(ndmap,&ndmapi);CHKERRQ(ierr);
440     for (i = 0, cnt = 0; i < A->rmap->n; i++)
441       if (ndmapi[i] < 0 && ndmapc[i] < 2)
442         cnt++;
443 
444     ierr = MPIU_Allreduce(&cnt,&i,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
445     if (i) { /* we detected isolated separator nodes */
446       Mat                    A2,A3;
447       IS                     *workis,is2;
448       PetscScalar            *vals;
449       PetscInt               gcnt = i,*dnz,*onz,j,*lndmapi;
450       ISLocalToGlobalMapping ll2g;
451       PetscBool              flg;
452       const PetscInt         *ii,*jj;
453 
454       /* communicate global id of separators */
455       ierr = MatPreallocateInitialize(comm,A->rmap->n,A->cmap->n,dnz,onz);CHKERRQ(ierr);
456       for (i = 0, cnt = 0; i < A->rmap->n; i++)
457         dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1;
458 
459       ierr = PetscMalloc1(nl,&lndmapi);CHKERRQ(ierr);
460       ierr = PetscSFBcastBegin(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr);
461 
462       /* compute adjacency of isolated separators node */
463       ierr = PetscMalloc1(gcnt,&workis);CHKERRQ(ierr);
464       for (i = 0, cnt = 0; i < A->rmap->n; i++) {
465         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
466           ierr = ISCreateStride(comm,1,i+A->rmap->rstart,1,&workis[cnt++]);CHKERRQ(ierr);
467         }
468       }
469       for (i = cnt; i < gcnt; i++) {
470         ierr = ISCreateStride(comm,0,0,1,&workis[i]);CHKERRQ(ierr);
471       }
472       for (i = 0; i < gcnt; i++) {
473         ierr = PetscObjectSetName((PetscObject)workis[i],"ISOLATED");CHKERRQ(ierr);
474         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
475       }
476 
477       /* no communications since all the ISes correspond to locally owned rows */
478       ierr = MatIncreaseOverlap(A,gcnt,workis,1);CHKERRQ(ierr);
479 
480       /* end communicate global id of separators */
481       ierr = PetscSFBcastEnd(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr);
482 
483       /* communicate new layers : create a matrix and transpose it */
484       ierr = PetscMemzero(dnz,A->rmap->n*sizeof(*dnz));CHKERRQ(ierr);
485       ierr = PetscMemzero(onz,A->rmap->n*sizeof(*onz));CHKERRQ(ierr);
486       for (i = 0, j = 0; i < A->rmap->n; i++) {
487         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
488           const PetscInt* idxs;
489           PetscInt        s;
490 
491           ierr = ISGetLocalSize(workis[j],&s);CHKERRQ(ierr);
492           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
493           ierr = MatPreallocateSet(i+A->rmap->rstart,s,idxs,dnz,onz);CHKERRQ(ierr);
494           j++;
495         }
496       }
497       if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt);
498 
499       for (i = 0; i < gcnt; i++) {
500         ierr = PetscObjectSetName((PetscObject)workis[i],"EXTENDED");CHKERRQ(ierr);
501         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
502       }
503 
504       for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j,dnz[i]+onz[i]);
505       ierr = PetscMalloc1(j,&vals);CHKERRQ(ierr);
506       for (i = 0; i < j; i++) vals[i] = 1.0;
507 
508       ierr = MatCreate(comm,&A2);CHKERRQ(ierr);
509       ierr = MatSetType(A2,MATMPIAIJ);CHKERRQ(ierr);
510       ierr = MatSetSizes(A2,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
511       ierr = MatMPIAIJSetPreallocation(A2,0,dnz,0,onz);CHKERRQ(ierr);
512       ierr = MatSetOption(A2,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
513       for (i = 0, j = 0; i < A2->rmap->n; i++) {
514         PetscInt        row = i+A2->rmap->rstart,s = dnz[i] + onz[i];
515         const PetscInt* idxs;
516 
517         if (s) {
518           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
519           ierr = MatSetValues(A2,1,&row,s,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
520           ierr = ISRestoreIndices(workis[j],&idxs);CHKERRQ(ierr);
521           j++;
522         }
523       }
524       if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt);
525       ierr = PetscFree(vals);CHKERRQ(ierr);
526       ierr = MatAssemblyBegin(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
527       ierr = MatAssemblyEnd(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
528       ierr = MatTranspose(A2,MAT_INPLACE_MATRIX,&A2);CHKERRQ(ierr);
529 
530       /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */
531       for (i = 0, j = 0; i < nl; i++)
532         if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i];
533       ierr = ISCreateGeneral(comm,j,lndmapi,PETSC_USE_POINTER,&is);CHKERRQ(ierr);
534       ierr = MatMPIAIJGetLocalMatCondensed(A2,MAT_INITIAL_MATRIX,&is,NULL,&A3);CHKERRQ(ierr);
535       ierr = ISDestroy(&is);CHKERRQ(ierr);
536       ierr = MatDestroy(&A2);CHKERRQ(ierr);
537 
538       /* extend local to global map to include connected isolated separators */
539       ierr = PetscObjectQuery((PetscObject)A3,"_petsc_GetLocalMatCondensed_iscol",(PetscObject*)&is);CHKERRQ(ierr);
540       if (!is) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing column map");
541       ierr = ISLocalToGlobalMappingCreateIS(is,&ll2g);CHKERRQ(ierr);
542       ierr = MatGetRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
543       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
544       ierr = ISCreateGeneral(PETSC_COMM_SELF,ii[i],jj,PETSC_COPY_VALUES,&is);CHKERRQ(ierr);
545       ierr = MatRestoreRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
546       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
547       ierr = ISLocalToGlobalMappingApplyIS(ll2g,is,&is2);CHKERRQ(ierr);
548       ierr = ISDestroy(&is);CHKERRQ(ierr);
549       ierr = ISLocalToGlobalMappingDestroy(&ll2g);CHKERRQ(ierr);
550 
551       /* add new nodes to the local-to-global map */
552       ierr = ISLocalToGlobalMappingDestroy(l2g);CHKERRQ(ierr);
553       ierr = ISExpand(ndsub,is2,&is);CHKERRQ(ierr);
554       ierr = ISDestroy(&is2);CHKERRQ(ierr);
555       ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
556       ierr = ISDestroy(&is);CHKERRQ(ierr);
557 
558       ierr = MatDestroy(&A3);CHKERRQ(ierr);
559       ierr = PetscFree(lndmapi);CHKERRQ(ierr);
560       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
561       for (i = 0; i < gcnt; i++) {
562         ierr = ISDestroy(&workis[i]);CHKERRQ(ierr);
563       }
564       ierr = PetscFree(workis);CHKERRQ(ierr);
565     }
566     ierr = ISRestoreIndices(ndmap,&ndmapi);CHKERRQ(ierr);
567     ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
568     ierr = PetscFree(ndmapc);CHKERRQ(ierr);
569     ierr = ISDestroy(&ndmap);CHKERRQ(ierr);
570     ierr = ISDestroy(&ndsub);CHKERRQ(ierr);
571     ierr = ISLocalToGlobalMappingSetBlockSize(*l2g,bs);CHKERRQ(ierr);
572     ierr = ISLocalToGlobalMappingViewFromOptions(*l2g,NULL,"-matis_nd_l2g_view");CHKERRQ(ierr);
573     break;
574   case MAT_IS_DISASSEMBLE_L2G_NATURAL:
575     if (ismpiaij) {
576       ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
577     } else if (ismpibaij) {
578       ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
579     } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
580     if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
581     if (A->rmap->n) {
582       PetscInt dc,oc,stc,*aux;
583 
584       ierr = MatGetLocalSize(A,NULL,&dc);CHKERRQ(ierr);
585       ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
586       ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
587       ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
588       for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
589       for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
590       ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
591     } else {
592       ierr = ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
593     }
594     ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
595     ierr = ISDestroy(&is);CHKERRQ(ierr);
596     break;
597   default:
598     SETERRQ1(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %D",mode);
599   }
600   PetscFunctionReturn(0);
601 }
602 
603 PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
604 {
605   Mat                    lA,Ad,Ao,B = NULL;
606   ISLocalToGlobalMapping rl2g,cl2g;
607   IS                     is;
608   MPI_Comm               comm;
609   void                   *ptrs[2];
610   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
611   const PetscInt         *garray;
612   PetscScalar            *dd,*od,*aa,*data;
613   const PetscInt         *di,*dj,*oi,*oj;
614   const PetscInt         *odi,*odj,*ooi,*ooj;
615   PetscInt               *aux,*ii,*jj;
616   PetscInt               bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
617   PetscBool              flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE;
618   PetscMPIInt            size;
619   PetscErrorCode         ierr;
620 
621   PetscFunctionBegin;
622   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
623   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
624   if (size == 1) {
625     ierr = MatConvert_SeqXAIJ_IS(A,type,reuse,newmat);CHKERRQ(ierr);
626     PetscFunctionReturn(0);
627   }
628   if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) {
629     ierr = MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g);CHKERRQ(ierr);
630     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
631     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
632     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
633     ierr = MatSetLocalToGlobalMapping(B,rl2g,rl2g);CHKERRQ(ierr);
634     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
635     ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
636     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
637     if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE;
638     reuse = MAT_REUSE_MATRIX;
639   }
640   if (reuse == MAT_REUSE_MATRIX) {
641     Mat            *newlA, lA;
642     IS             rows, cols;
643     const PetscInt *ridx, *cidx;
644     PetscInt       rbs, cbs, nr, nc;
645 
646     if (!B) B = *newmat;
647     ierr = MatGetLocalToGlobalMapping(B,&rl2g,&cl2g);CHKERRQ(ierr);
648     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
649     ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
650     ierr = ISLocalToGlobalMappingGetSize(rl2g,&nr);CHKERRQ(ierr);
651     ierr = ISLocalToGlobalMappingGetSize(cl2g,&nc);CHKERRQ(ierr);
652     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs);CHKERRQ(ierr);
653     ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs);CHKERRQ(ierr);
654     ierr = ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
655     if (rl2g != cl2g) {
656       ierr = ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
657     } else {
658       ierr = PetscObjectReference((PetscObject)rows);CHKERRQ(ierr);
659       cols = rows;
660     }
661     ierr = MatISGetLocalMat(B,&lA);CHKERRQ(ierr);
662     ierr = MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
663     ierr = MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0]);CHKERRQ(ierr);
664     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
665     ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
666     ierr = ISDestroy(&rows);CHKERRQ(ierr);
667     ierr = ISDestroy(&cols);CHKERRQ(ierr);
668     if (!lA->preallocated) { /* first time */
669       ierr = MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA);CHKERRQ(ierr);
670       ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
671       ierr = PetscObjectDereference((PetscObject)lA);CHKERRQ(ierr);
672     }
673     ierr = MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
674     ierr = MatDestroySubMatrices(1,&newlA);CHKERRQ(ierr);
675     ierr = MatISScaleDisassembling_Private(B);CHKERRQ(ierr);
676     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
677     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
678     if (was_inplace) { ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); }
679     else *newmat = B;
680     PetscFunctionReturn(0);
681   }
682   /* rectangular case, just compress out the column space */
683   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
684   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
685   if (ismpiaij) {
686     bs   = 1;
687     ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
688   } else if (ismpibaij) {
689     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
690     ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
691     ierr = MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad);CHKERRQ(ierr);
692     ierr = MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao);CHKERRQ(ierr);
693   } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
694   ierr = MatSeqAIJGetArray(Ad,&dd);CHKERRQ(ierr);
695   ierr = MatSeqAIJGetArray(Ao,&od);CHKERRQ(ierr);
696   if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
697 
698   /* access relevant information from MPIAIJ */
699   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
700   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
701   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
702   ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
703   ierr = MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg);CHKERRQ(ierr);
704   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
705   ierr = MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg);CHKERRQ(ierr);
706   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
707   nnz = di[dr] + oi[dr];
708   /* store original pointers to be restored later */
709   odi = di; odj = dj; ooi = oi; ooj = oj;
710 
711   /* generate l2g maps for rows and cols */
712   ierr = ISCreateStride(comm,dr/bs,str/bs,1,&is);CHKERRQ(ierr);
713   if (bs > 1) {
714     IS is2;
715 
716     ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
717     ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
718     ierr = ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
719     ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
720     ierr = ISDestroy(&is);CHKERRQ(ierr);
721     is   = is2;
722   }
723   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
724   ierr = ISDestroy(&is);CHKERRQ(ierr);
725   if (dr) {
726     ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
727     for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
728     for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
729     ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
730     lc   = dc+oc;
731   } else {
732     ierr = ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
733     lc   = 0;
734   }
735   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
736   ierr = ISDestroy(&is);CHKERRQ(ierr);
737 
738   /* create MATIS object */
739   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
740   ierr = MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
741   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
742   ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
743   ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
744   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
745   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
746 
747   /* merge local matrices */
748   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
749   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
750   ii   = aux;
751   jj   = aux+dr+1;
752   aa   = data;
753   *ii  = *(di++) + *(oi++);
754   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
755   {
756      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
757      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
758      *(++ii) = *(di++) + *(oi++);
759   }
760   for (;cum<dr;cum++) *(++ii) = nnz;
761 
762   ierr = MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg);CHKERRQ(ierr);
763   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
764   ierr = MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg);CHKERRQ(ierr);
765   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
766   ierr = MatSeqAIJRestoreArray(Ad,&dd);CHKERRQ(ierr);
767   ierr = MatSeqAIJRestoreArray(Ao,&od);CHKERRQ(ierr);
768 
769   ii   = aux;
770   jj   = aux+dr+1;
771   aa   = data;
772   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
773 
774   /* create containers to destroy the data */
775   ptrs[0] = aux;
776   ptrs[1] = data;
777   for (i=0; i<2; i++) {
778     PetscContainer c;
779 
780     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
781     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
782     ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
783     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
784     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
785   }
786   if (ismpibaij) { /* destroy converted local matrices */
787     ierr = MatDestroy(&Ad);CHKERRQ(ierr);
788     ierr = MatDestroy(&Ao);CHKERRQ(ierr);
789   }
790 
791   /* finalize matrix */
792   ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
793   ierr = MatDestroy(&lA);CHKERRQ(ierr);
794   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
795   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
796   if (reuse == MAT_INPLACE_MATRIX) {
797     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
798   } else *newmat = B;
799   PetscFunctionReturn(0);
800 }
801 
802 PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
803 {
804   Mat                    **nest,*snest,**rnest,lA,B;
805   IS                     *iscol,*isrow,*islrow,*islcol;
806   ISLocalToGlobalMapping rl2g,cl2g;
807   MPI_Comm               comm;
808   PetscInt               *lr,*lc,*l2gidxs;
809   PetscInt               i,j,nr,nc,rbs,cbs;
810   PetscBool              convert,lreuse,*istrans;
811   PetscErrorCode         ierr;
812 
813   PetscFunctionBegin;
814   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
815   lreuse = PETSC_FALSE;
816   rnest  = NULL;
817   if (reuse == MAT_REUSE_MATRIX) {
818     PetscBool ismatis,isnest;
819 
820     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
821     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
822     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
823     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
824     if (isnest) {
825       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
826       lreuse = (PetscBool)(i == nr && j == nc);
827       if (!lreuse) rnest = NULL;
828     }
829   }
830   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
831   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
832   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
833                       nr,&islrow,nc,&islcol,
834                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
835   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
836   for (i=0;i<nr;i++) {
837     for (j=0;j<nc;j++) {
838       PetscBool ismatis;
839       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
840 
841       /* Null matrix pointers are allowed in MATNEST */
842       if (!nest[i][j]) continue;
843 
844       /* Nested matrices should be of type MATIS */
845       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
846       if (istrans[ij]) {
847         Mat T,lT;
848         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
849         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
850         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) (transposed) is not of type MATIS",i,j);
851         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
852         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
853       } else {
854         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
855         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) is not of type MATIS",i,j);
856         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
857       }
858 
859       /* Check compatibility of local sizes */
860       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
861       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
862       if (!l1 || !l2) continue;
863       if (lr[i] && l1 != lr[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lr[i],l1);
864       if (lc[j] && l2 != lc[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lc[j],l2);
865       lr[i] = l1;
866       lc[j] = l2;
867 
868       /* check compatibilty for local matrix reusage */
869       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
870     }
871   }
872 
873 #if defined (PETSC_USE_DEBUG)
874   /* Check compatibility of l2g maps for rows */
875   for (i=0;i<nr;i++) {
876     rl2g = NULL;
877     for (j=0;j<nc;j++) {
878       PetscInt n1,n2;
879 
880       if (!nest[i][j]) continue;
881       if (istrans[i*nc+j]) {
882         Mat T;
883 
884         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
885         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
886       } else {
887         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
888       }
889       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
890       if (!n1) continue;
891       if (!rl2g) {
892         rl2g = cl2g;
893       } else {
894         const PetscInt *idxs1,*idxs2;
895         PetscBool      same;
896 
897         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
898         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap size %D != %D",i,j,n1,n2);
899         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
900         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
901         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
902         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
903         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
904         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap",i,j);
905       }
906     }
907   }
908   /* Check compatibility of l2g maps for columns */
909   for (i=0;i<nc;i++) {
910     rl2g = NULL;
911     for (j=0;j<nr;j++) {
912       PetscInt n1,n2;
913 
914       if (!nest[j][i]) continue;
915       if (istrans[j*nc+i]) {
916         Mat T;
917 
918         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
919         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
920       } else {
921         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
922       }
923       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
924       if (!n1) continue;
925       if (!rl2g) {
926         rl2g = cl2g;
927       } else {
928         const PetscInt *idxs1,*idxs2;
929         PetscBool      same;
930 
931         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
932         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap size %D != %D",j,i,n1,n2);
933         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
934         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
935         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
936         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
937         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
938         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap",j,i);
939       }
940     }
941   }
942 #endif
943 
944   B = NULL;
945   if (reuse != MAT_REUSE_MATRIX) {
946     PetscInt stl;
947 
948     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
949     for (i=0,stl=0;i<nr;i++) stl += lr[i];
950     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
951     for (i=0,stl=0;i<nr;i++) {
952       Mat            usedmat;
953       Mat_IS         *matis;
954       const PetscInt *idxs;
955 
956       /* local IS for local NEST */
957       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
958 
959       /* l2gmap */
960       j = 0;
961       usedmat = nest[i][j];
962       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
963       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
964 
965       if (istrans[i*nc+j]) {
966         Mat T;
967         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
968         usedmat = T;
969       }
970       matis = (Mat_IS*)(usedmat->data);
971       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
972       if (istrans[i*nc+j]) {
973         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
974         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
975       } else {
976         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
977         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
978       }
979       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
980       stl += lr[i];
981     }
982     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
983 
984     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
985     for (i=0,stl=0;i<nc;i++) stl += lc[i];
986     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
987     for (i=0,stl=0;i<nc;i++) {
988       Mat            usedmat;
989       Mat_IS         *matis;
990       const PetscInt *idxs;
991 
992       /* local IS for local NEST */
993       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
994 
995       /* l2gmap */
996       j = 0;
997       usedmat = nest[j][i];
998       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
999       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
1000       if (istrans[j*nc+i]) {
1001         Mat T;
1002         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
1003         usedmat = T;
1004       }
1005       matis = (Mat_IS*)(usedmat->data);
1006       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
1007       if (istrans[j*nc+i]) {
1008         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
1009         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
1010       } else {
1011         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
1012         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
1013       }
1014       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
1015       stl += lc[i];
1016     }
1017     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
1018 
1019     /* Create MATIS */
1020     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
1021     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
1022     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
1023     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
1024     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
1025     ierr = MatISSetLocalMatType(B,MATNEST);CHKERRQ(ierr);
1026     { /* hack : avoid setup of scatters */
1027       Mat_IS *matis = (Mat_IS*)(B->data);
1028       matis->islocalref = PETSC_TRUE;
1029     }
1030     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
1031     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1032     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1033     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
1034     ierr = MatNestSetVecType(lA,VECNEST);CHKERRQ(ierr);
1035     for (i=0;i<nr*nc;i++) {
1036       if (istrans[i]) {
1037         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
1038       }
1039     }
1040     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
1041     ierr = MatDestroy(&lA);CHKERRQ(ierr);
1042     { /* hack : setup of scatters done here */
1043       Mat_IS *matis = (Mat_IS*)(B->data);
1044 
1045       matis->islocalref = PETSC_FALSE;
1046       ierr = MatISSetUpScatters_Private(B);CHKERRQ(ierr);
1047     }
1048     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1049     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1050     if (reuse == MAT_INPLACE_MATRIX) {
1051       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
1052     } else {
1053       *newmat = B;
1054     }
1055   } else {
1056     if (lreuse) {
1057       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
1058       for (i=0;i<nr;i++) {
1059         for (j=0;j<nc;j++) {
1060           if (snest[i*nc+j]) {
1061             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
1062             if (istrans[i*nc+j]) {
1063               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
1064             }
1065           }
1066         }
1067       }
1068     } else {
1069       PetscInt stl;
1070       for (i=0,stl=0;i<nr;i++) {
1071         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
1072         stl  += lr[i];
1073       }
1074       for (i=0,stl=0;i<nc;i++) {
1075         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
1076         stl  += lc[i];
1077       }
1078       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
1079       for (i=0;i<nr*nc;i++) {
1080         if (istrans[i]) {
1081           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
1082         }
1083       }
1084       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
1085       ierr = MatDestroy(&lA);CHKERRQ(ierr);
1086     }
1087     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1088     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1089   }
1090 
1091   /* Create local matrix in MATNEST format */
1092   convert = PETSC_FALSE;
1093   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
1094   if (convert) {
1095     Mat              M;
1096     MatISLocalFields lf;
1097     PetscContainer   c;
1098 
1099     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
1100     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
1101     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
1102     ierr = MatDestroy(&M);CHKERRQ(ierr);
1103 
1104     /* attach local fields to the matrix */
1105     ierr = PetscNew(&lf);CHKERRQ(ierr);
1106     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
1107     for (i=0;i<nr;i++) {
1108       PetscInt n,st;
1109 
1110       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
1111       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
1112       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
1113     }
1114     for (i=0;i<nc;i++) {
1115       PetscInt n,st;
1116 
1117       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
1118       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
1119       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
1120     }
1121     lf->nr = nr;
1122     lf->nc = nc;
1123     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
1124     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
1125     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
1126     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
1127     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
1128   }
1129 
1130   /* Free workspace */
1131   for (i=0;i<nr;i++) {
1132     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
1133   }
1134   for (i=0;i<nc;i++) {
1135     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
1136   }
1137   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
1138   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
1139   PetscFunctionReturn(0);
1140 }
1141 
1142 static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
1143 {
1144   Mat_IS            *matis = (Mat_IS*)A->data;
1145   Vec               ll,rr;
1146   const PetscScalar *Y,*X;
1147   PetscScalar       *x,*y;
1148   PetscErrorCode    ierr;
1149 
1150   PetscFunctionBegin;
1151   if (l) {
1152     ll   = matis->y;
1153     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
1154     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
1155     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1156   } else {
1157     ll = NULL;
1158   }
1159   if (r) {
1160     rr   = matis->x;
1161     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
1162     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
1163     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1164   } else {
1165     rr = NULL;
1166   }
1167   if (ll) {
1168     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1169     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
1170     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
1171   }
1172   if (rr) {
1173     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1174     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
1175     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
1176   }
1177   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
1178   PetscFunctionReturn(0);
1179 }
1180 
1181 static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
1182 {
1183   Mat_IS         *matis = (Mat_IS*)A->data;
1184   MatInfo        info;
1185   PetscReal      isend[6],irecv[6];
1186   PetscInt       bs;
1187   PetscErrorCode ierr;
1188 
1189   PetscFunctionBegin;
1190   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
1191   if (matis->A->ops->getinfo) {
1192     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
1193     isend[0] = info.nz_used;
1194     isend[1] = info.nz_allocated;
1195     isend[2] = info.nz_unneeded;
1196     isend[3] = info.memory;
1197     isend[4] = info.mallocs;
1198   } else {
1199     isend[0] = 0.;
1200     isend[1] = 0.;
1201     isend[2] = 0.;
1202     isend[3] = 0.;
1203     isend[4] = 0.;
1204   }
1205   isend[5] = matis->A->num_ass;
1206   if (flag == MAT_LOCAL) {
1207     ginfo->nz_used      = isend[0];
1208     ginfo->nz_allocated = isend[1];
1209     ginfo->nz_unneeded  = isend[2];
1210     ginfo->memory       = isend[3];
1211     ginfo->mallocs      = isend[4];
1212     ginfo->assemblies   = isend[5];
1213   } else if (flag == MAT_GLOBAL_MAX) {
1214     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1215 
1216     ginfo->nz_used      = irecv[0];
1217     ginfo->nz_allocated = irecv[1];
1218     ginfo->nz_unneeded  = irecv[2];
1219     ginfo->memory       = irecv[3];
1220     ginfo->mallocs      = irecv[4];
1221     ginfo->assemblies   = irecv[5];
1222   } else if (flag == MAT_GLOBAL_SUM) {
1223     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1224 
1225     ginfo->nz_used      = irecv[0];
1226     ginfo->nz_allocated = irecv[1];
1227     ginfo->nz_unneeded  = irecv[2];
1228     ginfo->memory       = irecv[3];
1229     ginfo->mallocs      = irecv[4];
1230     ginfo->assemblies   = A->num_ass;
1231   }
1232   ginfo->block_size        = bs;
1233   ginfo->fill_ratio_given  = 0;
1234   ginfo->fill_ratio_needed = 0;
1235   ginfo->factor_mallocs    = 0;
1236   PetscFunctionReturn(0);
1237 }
1238 
1239 PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
1240 {
1241   Mat                    C,lC,lA;
1242   PetscErrorCode         ierr;
1243 
1244   PetscFunctionBegin;
1245   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
1246     ISLocalToGlobalMapping rl2g,cl2g;
1247     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
1248     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
1249     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
1250     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
1251     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
1252     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
1253   } else {
1254     C = *B;
1255   }
1256 
1257   /* perform local transposition */
1258   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1259   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
1260   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
1261   ierr = MatDestroy(&lC);CHKERRQ(ierr);
1262 
1263   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
1264     *B = C;
1265   } else {
1266     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
1267   }
1268   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1269   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1270   PetscFunctionReturn(0);
1271 }
1272 
1273 PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
1274 {
1275   Mat_IS         *is = (Mat_IS*)A->data;
1276   PetscErrorCode ierr;
1277 
1278   PetscFunctionBegin;
1279   if (D) { /* MatShift_IS pass D = NULL */
1280     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1281     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1282   }
1283   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
1284   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
1285   PetscFunctionReturn(0);
1286 }
1287 
1288 PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
1289 {
1290   Mat_IS         *is = (Mat_IS*)A->data;
1291   PetscErrorCode ierr;
1292 
1293   PetscFunctionBegin;
1294   ierr = VecSet(is->y,a);CHKERRQ(ierr);
1295   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
1296   PetscFunctionReturn(0);
1297 }
1298 
1299 static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1300 {
1301   PetscErrorCode ierr;
1302   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1303 
1304   PetscFunctionBegin;
1305 #if defined(PETSC_USE_DEBUG)
1306   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
1307 #endif
1308   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1309   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1310   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1311   PetscFunctionReturn(0);
1312 }
1313 
1314 static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1315 {
1316   PetscErrorCode ierr;
1317   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1318 
1319   PetscFunctionBegin;
1320 #if defined(PETSC_USE_DEBUG)
1321   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
1322 #endif
1323   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1324   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1325   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1326   PetscFunctionReturn(0);
1327 }
1328 
1329 static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
1330 {
1331   PetscInt      *owners = map->range;
1332   PetscInt       n      = map->n;
1333   PetscSF        sf;
1334   PetscInt      *lidxs,*work = NULL;
1335   PetscSFNode   *ridxs;
1336   PetscMPIInt    rank;
1337   PetscInt       r, p = 0, len = 0;
1338   PetscErrorCode ierr;
1339 
1340   PetscFunctionBegin;
1341   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
1342   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
1343   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
1344   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
1345   for (r = 0; r < n; ++r) lidxs[r] = -1;
1346   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
1347   for (r = 0; r < N; ++r) {
1348     const PetscInt idx = idxs[r];
1349     if (idx < 0 || map->N <= idx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index %D out of range [0,%D)",idx,map->N);
1350     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
1351       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
1352     }
1353     ridxs[r].rank = p;
1354     ridxs[r].index = idxs[r] - owners[p];
1355   }
1356   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
1357   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
1358   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
1359   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
1360   if (ogidxs) { /* communicate global idxs */
1361     PetscInt cum = 0,start,*work2;
1362 
1363     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1364     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
1365     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
1366     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
1367     start -= cum;
1368     cum = 0;
1369     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
1370     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
1371     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
1372     ierr = PetscFree(work2);CHKERRQ(ierr);
1373   }
1374   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
1375   /* Compress and put in indices */
1376   for (r = 0; r < n; ++r)
1377     if (lidxs[r] >= 0) {
1378       if (work) work[len] = work[r];
1379       lidxs[len++] = r;
1380     }
1381   if (on) *on = len;
1382   if (oidxs) *oidxs = lidxs;
1383   if (ogidxs) *ogidxs = work;
1384   PetscFunctionReturn(0);
1385 }
1386 
1387 static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
1388 {
1389   Mat               locmat,newlocmat;
1390   Mat_IS            *newmatis;
1391 #if defined(PETSC_USE_DEBUG)
1392   Vec               rtest,ltest;
1393   const PetscScalar *array;
1394 #endif
1395   const PetscInt    *idxs;
1396   PetscInt          i,m,n;
1397   PetscErrorCode    ierr;
1398 
1399   PetscFunctionBegin;
1400   if (scall == MAT_REUSE_MATRIX) {
1401     PetscBool ismatis;
1402 
1403     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1404     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1405     newmatis = (Mat_IS*)(*newmat)->data;
1406     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
1407     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1408   }
1409   /* irow and icol may not have duplicate entries */
1410 #if defined(PETSC_USE_DEBUG)
1411   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
1412   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
1413   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1414   for (i=0;i<n;i++) {
1415     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1416   }
1417   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
1418   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
1419   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
1420   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
1421   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
1422   for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Irow may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
1423   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
1424   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
1425   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1426   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1427   for (i=0;i<n;i++) {
1428     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1429   }
1430   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
1431   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
1432   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
1433   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
1434   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
1435   for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Icol may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
1436   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
1437   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
1438   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
1439   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
1440 #endif
1441   if (scall == MAT_INITIAL_MATRIX) {
1442     Mat_IS                 *matis = (Mat_IS*)mat->data;
1443     ISLocalToGlobalMapping rl2g;
1444     IS                     is;
1445     PetscInt               *lidxs,*lgidxs,*newgidxs;
1446     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
1447     PetscBool              cong;
1448     MPI_Comm               comm;
1449 
1450     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
1451     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
1452     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
1453     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
1454     rbs  = arbs == irbs ? irbs : 1;
1455     cbs  = acbs == icbs ? icbs : 1;
1456     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
1457     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1458     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1459     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1460     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1461     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
1462     /* communicate irow to their owners in the layout */
1463     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1464     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1465     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
1466     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1467     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
1468     ierr = PetscFree(lidxs);CHKERRQ(ierr);
1469     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1470     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1471     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1472     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
1473     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1474     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
1475     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1476       if (matis->sf_leafdata[i]) {
1477         lidxs[newloc] = i;
1478         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1479       }
1480     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1481     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1482     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
1483     ierr = ISDestroy(&is);CHKERRQ(ierr);
1484     /* local is to extract local submatrix */
1485     newmatis = (Mat_IS*)(*newmat)->data;
1486     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
1487     ierr = MatHasCongruentLayouts(mat,&cong);CHKERRQ(ierr);
1488     if (cong && irow == icol && matis->csf == matis->sf) {
1489       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
1490       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
1491       newmatis->getsub_cis = newmatis->getsub_ris;
1492     } else {
1493       ISLocalToGlobalMapping cl2g;
1494 
1495       /* communicate icol to their owners in the layout */
1496       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1497       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1498       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
1499       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1500       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
1501       ierr = PetscFree(lidxs);CHKERRQ(ierr);
1502       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1503       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
1504       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
1505       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
1506       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1507       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
1508       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1509         if (matis->csf_leafdata[i]) {
1510           lidxs[newloc] = i;
1511           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1512         }
1513       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1514       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1515       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
1516       ierr = ISDestroy(&is);CHKERRQ(ierr);
1517       /* local is to extract local submatrix */
1518       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
1519       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1520       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1521     }
1522     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1523   } else {
1524     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
1525   }
1526   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
1527   newmatis = (Mat_IS*)(*newmat)->data;
1528   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
1529   if (scall == MAT_INITIAL_MATRIX) {
1530     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
1531     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
1532   }
1533   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1534   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1535   PetscFunctionReturn(0);
1536 }
1537 
1538 static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
1539 {
1540   Mat_IS         *a = (Mat_IS*)A->data,*b;
1541   PetscBool      ismatis;
1542   PetscErrorCode ierr;
1543 
1544   PetscFunctionBegin;
1545   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
1546   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
1547   b = (Mat_IS*)B->data;
1548   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
1549   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
1550   PetscFunctionReturn(0);
1551 }
1552 
1553 static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
1554 {
1555   Vec               v;
1556   const PetscScalar *array;
1557   PetscInt          i,n;
1558   PetscErrorCode    ierr;
1559 
1560   PetscFunctionBegin;
1561   *missing = PETSC_FALSE;
1562   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
1563   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
1564   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1565   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
1566   for (i=0;i<n;i++) if (array[i] == 0.) break;
1567   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
1568   ierr = VecDestroy(&v);CHKERRQ(ierr);
1569   if (i != n) *missing = PETSC_TRUE;
1570   if (d) {
1571     *d = -1;
1572     if (*missing) {
1573       PetscInt rstart;
1574       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
1575       *d = i+rstart;
1576     }
1577   }
1578   PetscFunctionReturn(0);
1579 }
1580 
1581 static PetscErrorCode MatISSetUpSF_IS(Mat B)
1582 {
1583   Mat_IS         *matis = (Mat_IS*)(B->data);
1584   const PetscInt *gidxs;
1585   PetscInt       nleaves;
1586   PetscErrorCode ierr;
1587 
1588   PetscFunctionBegin;
1589   if (matis->sf) PetscFunctionReturn(0);
1590   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
1591   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
1592   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
1593   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
1594   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
1595   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
1596   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
1597     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
1598     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
1599     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
1600     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
1601     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
1602     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
1603   } else {
1604     matis->csf = matis->sf;
1605     matis->csf_leafdata = matis->sf_leafdata;
1606     matis->csf_rootdata = matis->sf_rootdata;
1607   }
1608   PetscFunctionReturn(0);
1609 }
1610 
1611 /*@
1612    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
1613 
1614    Collective on MPI_Comm
1615 
1616    Input Parameters:
1617 +  A - the matrix
1618 -  store - the boolean flag
1619 
1620    Level: advanced
1621 
1622    Notes:
1623 
1624 .keywords: matrix
1625 
1626 .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP()
1627 @*/
1628 PetscErrorCode  MatISStoreL2L(Mat A, PetscBool store)
1629 {
1630   PetscErrorCode ierr;
1631 
1632   PetscFunctionBegin;
1633   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1634   PetscValidType(A,1);
1635   PetscValidLogicalCollectiveBool(A,store,2);
1636   ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr);
1637   PetscFunctionReturn(0);
1638 }
1639 
1640 static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
1641 {
1642   Mat_IS         *matis = (Mat_IS*)(A->data);
1643   PetscErrorCode ierr;
1644 
1645   PetscFunctionBegin;
1646   matis->storel2l = store;
1647   if (!store) {
1648     ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr);
1649   }
1650   PetscFunctionReturn(0);
1651 }
1652 
1653 /*@
1654    MatISFixLocalEmpty - Compress out zero local rows from the local matrices
1655 
1656    Collective on MPI_Comm
1657 
1658    Input Parameters:
1659 +  A - the matrix
1660 -  fix - the boolean flag
1661 
1662    Level: advanced
1663 
1664    Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process.
1665 
1666 .keywords: matrix
1667 
1668 .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY
1669 @*/
1670 PetscErrorCode  MatISFixLocalEmpty(Mat A, PetscBool fix)
1671 {
1672   PetscErrorCode ierr;
1673 
1674   PetscFunctionBegin;
1675   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1676   PetscValidType(A,1);
1677   PetscValidLogicalCollectiveBool(A,fix,2);
1678   ierr = PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));CHKERRQ(ierr);
1679   PetscFunctionReturn(0);
1680 }
1681 
1682 static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix)
1683 {
1684   Mat_IS *matis = (Mat_IS*)(A->data);
1685 
1686   PetscFunctionBegin;
1687   matis->locempty = fix;
1688   PetscFunctionReturn(0);
1689 }
1690 
1691 /*@
1692    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1693 
1694    Collective on MPI_Comm
1695 
1696    Input Parameters:
1697 +  B - the matrix
1698 .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1699            (same value is used for all local rows)
1700 .  d_nnz - array containing the number of nonzeros in the various rows of the
1701            DIAGONAL portion of the local submatrix (possibly different for each row)
1702            or NULL, if d_nz is used to specify the nonzero structure.
1703            The size of this array is equal to the number of local rows, i.e 'm'.
1704            For matrices that will be factored, you must leave room for (and set)
1705            the diagonal entry even if it is zero.
1706 .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1707            submatrix (same value is used for all local rows).
1708 -  o_nnz - array containing the number of nonzeros in the various rows of the
1709            OFF-DIAGONAL portion of the local submatrix (possibly different for
1710            each row) or NULL, if o_nz is used to specify the nonzero
1711            structure. The size of this array is equal to the number
1712            of local rows, i.e 'm'.
1713 
1714    If the *_nnz parameter is given then the *_nz parameter is ignored
1715 
1716    Level: intermediate
1717 
1718    Notes:
1719     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1720           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1721           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1722 
1723 .keywords: matrix
1724 
1725 .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1726 @*/
1727 PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
1728 {
1729   PetscErrorCode ierr;
1730 
1731   PetscFunctionBegin;
1732   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
1733   PetscValidType(B,1);
1734   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
1735   PetscFunctionReturn(0);
1736 }
1737 
1738 /* this is used by DMDA */
1739 PETSC_EXTERN PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
1740 {
1741   Mat_IS         *matis = (Mat_IS*)(B->data);
1742   PetscInt       bs,i,nlocalcols;
1743   PetscErrorCode ierr;
1744 
1745   PetscFunctionBegin;
1746   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1747 
1748   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
1749   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
1750 
1751   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
1752   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
1753 
1754   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1755   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
1756   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
1757   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1758 
1759   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
1760   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
1761 #if defined(PETSC_HAVE_HYPRE)
1762   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
1763 #endif
1764 
1765   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
1766   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
1767 
1768   nlocalcols /= bs;
1769   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i);
1770   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
1771 
1772   /* for other matrix types */
1773   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
1774   PetscFunctionReturn(0);
1775 }
1776 
1777 PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
1778 {
1779   Mat_IS          *matis = (Mat_IS*)(A->data);
1780   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1781   const PetscInt  *global_indices_r,*global_indices_c;
1782   PetscInt        i,j,bs,rows,cols;
1783   PetscInt        lrows,lcols;
1784   PetscInt        local_rows,local_cols;
1785   PetscMPIInt     size;
1786   PetscBool       isdense,issbaij;
1787   PetscErrorCode  ierr;
1788 
1789   PetscFunctionBegin;
1790   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr);
1791   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
1792   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
1793   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1794   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
1795   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1796   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1797   if (A->rmap->mapping != A->cmap->mapping) {
1798     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1799   } else {
1800     global_indices_c = global_indices_r;
1801   }
1802 
1803   if (issbaij) {
1804     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
1805   }
1806   /*
1807      An SF reduce is needed to sum up properly on shared rows.
1808      Note that generally preallocation is not exact, since it overestimates nonzeros
1809   */
1810   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
1811   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
1812   /* All processes need to compute entire row ownership */
1813   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
1814   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1815   for (i=0;i<size;i++) {
1816     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
1817       row_ownership[j] = i;
1818     }
1819   }
1820   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1821 
1822   /*
1823      my_dnz and my_onz contains exact contribution to preallocation from each local mat
1824      then, they will be summed up properly. This way, preallocation is always sufficient
1825   */
1826   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
1827   /* preallocation as a MATAIJ */
1828   if (isdense) { /* special case for dense local matrices */
1829     for (i=0;i<local_rows;i++) {
1830       PetscInt owner = row_ownership[global_indices_r[i]];
1831       for (j=0;j<local_cols;j++) {
1832         PetscInt index_col = global_indices_c[j];
1833         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1834           my_dnz[i] += 1;
1835         } else { /* offdiag block */
1836           my_onz[i] += 1;
1837         }
1838       }
1839     }
1840   } else if (matis->A->ops->getrowij) {
1841     const PetscInt *ii,*jj,*jptr;
1842     PetscBool      done;
1843     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1844     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1845     jptr = jj;
1846     for (i=0;i<local_rows;i++) {
1847       PetscInt index_row = global_indices_r[i];
1848       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1849         PetscInt owner = row_ownership[index_row];
1850         PetscInt index_col = global_indices_c[*jptr];
1851         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1852           my_dnz[i] += 1;
1853         } else { /* offdiag block */
1854           my_onz[i] += 1;
1855         }
1856         /* same as before, interchanging rows and cols */
1857         if (issbaij && index_col != index_row) {
1858           owner = row_ownership[index_col];
1859           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1860             my_dnz[*jptr] += 1;
1861           } else {
1862             my_onz[*jptr] += 1;
1863           }
1864         }
1865       }
1866     }
1867     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1868     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1869   } else { /* loop over rows and use MatGetRow */
1870     for (i=0;i<local_rows;i++) {
1871       const PetscInt *cols;
1872       PetscInt       ncols,index_row = global_indices_r[i];
1873       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
1874       for (j=0;j<ncols;j++) {
1875         PetscInt owner = row_ownership[index_row];
1876         PetscInt index_col = global_indices_c[cols[j]];
1877         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1878           my_dnz[i] += 1;
1879         } else { /* offdiag block */
1880           my_onz[i] += 1;
1881         }
1882         /* same as before, interchanging rows and cols */
1883         if (issbaij && index_col != index_row) {
1884           owner = row_ownership[index_col];
1885           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1886             my_dnz[cols[j]] += 1;
1887           } else {
1888             my_onz[cols[j]] += 1;
1889           }
1890         }
1891       }
1892       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
1893     }
1894   }
1895   if (global_indices_c != global_indices_r) {
1896     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1897   }
1898   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1899   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1900 
1901   /* Reduce my_dnz and my_onz */
1902   if (maxreduce) {
1903     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
1904     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1905     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
1906     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1907   } else {
1908     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
1909     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1910     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
1911     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1912   }
1913   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
1914 
1915   /* Resize preallocation if overestimated */
1916   for (i=0;i<lrows;i++) {
1917     dnz[i] = PetscMin(dnz[i],lcols);
1918     onz[i] = PetscMin(onz[i],cols-lcols);
1919   }
1920 
1921   /* Set preallocation */
1922   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
1923   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
1924   for (i=0;i<lrows;i+=bs) {
1925     PetscInt b, d = dnz[i],o = onz[i];
1926 
1927     for (b=1;b<bs;b++) {
1928       d = PetscMax(d,dnz[i+b]);
1929       o = PetscMax(o,onz[i+b]);
1930     }
1931     dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs);
1932     onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs);
1933   }
1934   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
1935   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
1936   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
1937   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
1938   if (issbaij) {
1939     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
1940   }
1941   ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
1942   PetscFunctionReturn(0);
1943 }
1944 
1945 PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M)
1946 {
1947   Mat_IS         *matis = (Mat_IS*)(mat->data);
1948   Mat            local_mat,MT;
1949   PetscInt       rbs,cbs,rows,cols,lrows,lcols;
1950   PetscInt       local_rows,local_cols;
1951   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1952 #if defined (PETSC_USE_DEBUG)
1953   PetscBool      lb[4],bb[4];
1954 #endif
1955   PetscMPIInt    size;
1956   PetscScalar    *array;
1957   PetscErrorCode ierr;
1958 
1959   PetscFunctionBegin;
1960   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
1961   if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) {
1962     Mat      B;
1963     IS       irows = NULL,icols = NULL;
1964     PetscInt rbs,cbs;
1965 
1966     ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
1967     ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
1968     if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */
1969       IS             rows,cols;
1970       const PetscInt *ridxs,*cidxs;
1971       PetscInt       i,nw,*work;
1972 
1973       ierr = ISLocalToGlobalMappingGetBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
1974       ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&nw);CHKERRQ(ierr);
1975       nw   = nw/rbs;
1976       ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
1977       for (i=0;i<nw;i++) work[ridxs[i]] += 1;
1978       for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
1979       if (i == nw) {
1980         ierr = ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
1981         ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1982         ierr = ISInvertPermutation(rows,PETSC_DECIDE,&irows);CHKERRQ(ierr);
1983         ierr = ISDestroy(&rows);CHKERRQ(ierr);
1984       }
1985       ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
1986       ierr = PetscFree(work);CHKERRQ(ierr);
1987       if (irows && mat->rmap->mapping != mat->cmap->mapping) {
1988         ierr = ISLocalToGlobalMappingGetBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1989         ierr = ISLocalToGlobalMappingGetSize(mat->cmap->mapping,&nw);CHKERRQ(ierr);
1990         nw   = nw/cbs;
1991         ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
1992         for (i=0;i<nw;i++) work[cidxs[i]] += 1;
1993         for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
1994         if (i == nw) {
1995           ierr = ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
1996           ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1997           ierr = ISInvertPermutation(cols,PETSC_DECIDE,&icols);CHKERRQ(ierr);
1998           ierr = ISDestroy(&cols);CHKERRQ(ierr);
1999         }
2000         ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
2001         ierr = PetscFree(work);CHKERRQ(ierr);
2002       } else if (irows) {
2003         ierr  = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr);
2004         icols = irows;
2005       }
2006     } else {
2007       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows);CHKERRQ(ierr);
2008       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols);CHKERRQ(ierr);
2009       if (irows) { ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); }
2010       if (icols) { ierr = PetscObjectReference((PetscObject)icols);CHKERRQ(ierr); }
2011     }
2012     if (!irows || !icols) {
2013       ierr = ISDestroy(&icols);CHKERRQ(ierr);
2014       ierr = ISDestroy(&irows);CHKERRQ(ierr);
2015       goto general_assembly;
2016     }
2017     ierr = MatConvert(matis->A,(rbs == cbs && rbs > 1) ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
2018     if (reuse != MAT_INPLACE_MATRIX) {
2019       ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
2020       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows);CHKERRQ(ierr);
2021       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols);CHKERRQ(ierr);
2022     } else {
2023       Mat C;
2024 
2025       ierr = MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr);
2026       ierr = MatHeaderReplace(mat,&C);CHKERRQ(ierr);
2027     }
2028     ierr = MatDestroy(&B);CHKERRQ(ierr);
2029     ierr = ISDestroy(&icols);CHKERRQ(ierr);
2030     ierr = ISDestroy(&irows);CHKERRQ(ierr);
2031     PetscFunctionReturn(0);
2032   }
2033 general_assembly:
2034   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
2035   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
2036   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
2037   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
2038   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
2039   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
2040   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
2041   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
2042   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
2043   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
2044 #if defined (PETSC_USE_DEBUG)
2045   lb[0] = isseqdense;
2046   lb[1] = isseqaij;
2047   lb[2] = isseqbaij;
2048   lb[3] = isseqsbaij;
2049   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
2050   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
2051 #endif
2052 
2053   if (reuse != MAT_REUSE_MATRIX) {
2054     ierr = MatCreate(PetscObjectComm((PetscObject)mat),&MT);CHKERRQ(ierr);
2055     ierr = MatSetSizes(MT,lrows,lcols,rows,cols);CHKERRQ(ierr);
2056     ierr = MatSetType(MT,mtype);CHKERRQ(ierr);
2057     ierr = MatSetBlockSizes(MT,rbs,cbs);CHKERRQ(ierr);
2058     ierr = MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE);CHKERRQ(ierr);
2059   } else {
2060     PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols;
2061 
2062     /* some checks */
2063     MT   = *M;
2064     ierr = MatGetBlockSizes(MT,&mrbs,&mcbs);CHKERRQ(ierr);
2065     ierr = MatGetSize(MT,&mrows,&mcols);CHKERRQ(ierr);
2066     ierr = MatGetLocalSize(MT,&mlrows,&mlcols);CHKERRQ(ierr);
2067     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
2068     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
2069     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
2070     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
2071     if (mrbs != rbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%d != %d)",rbs,mrbs);
2072     if (mcbs != cbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%d != %d)",cbs,mcbs);
2073     ierr = MatZeroEntries(MT);CHKERRQ(ierr);
2074   }
2075 
2076   if (isseqsbaij || isseqbaij) {
2077     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
2078     isseqaij = PETSC_TRUE;
2079   } else {
2080     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
2081     local_mat = matis->A;
2082   }
2083 
2084   /* Set values */
2085   ierr = MatSetLocalToGlobalMapping(MT,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
2086   if (isseqdense) { /* special case for dense local matrices */
2087     PetscInt i,*dummy;
2088 
2089     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
2090     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
2091     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
2092     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
2093     ierr = MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
2094     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
2095     ierr = PetscFree(dummy);CHKERRQ(ierr);
2096   } else if (isseqaij) {
2097     const PetscInt *blocks;
2098     PetscInt       i,nvtxs,*xadj,*adjncy, nb;
2099     PetscBool      done;
2100 
2101     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2102     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
2103     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
2104     ierr = MatGetVariableBlockSizes(local_mat,&nb,&blocks);CHKERRQ(ierr);
2105     if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */
2106       PetscInt sum;
2107 
2108       for (i=0,sum=0;i<nb;i++) sum += blocks[i];
2109       if (sum == nvtxs) {
2110         PetscInt r;
2111 
2112         for (i=0,r=0;i<nb;i++) {
2113           if (blocks[i] != xadj[r+1] - xadj[r]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid block sizes prescribed for block %D: expected %D, got %D",i,blocks[i],xadj[r+1] - xadj[r]);
2114           ierr = MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],array+xadj[r],ADD_VALUES);CHKERRQ(ierr);
2115           r   += blocks[i];
2116         }
2117       } else {
2118         for (i=0;i<nvtxs;i++) {
2119           ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
2120         }
2121       }
2122     } else {
2123       for (i=0;i<nvtxs;i++) {
2124         ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
2125       }
2126     }
2127     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2128     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
2129     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
2130   } else { /* very basic values insertion for all other matrix types */
2131     PetscInt i;
2132 
2133     for (i=0;i<local_rows;i++) {
2134       PetscInt       j;
2135       const PetscInt *local_indices_cols;
2136 
2137       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2138       ierr = MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
2139       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2140     }
2141   }
2142   ierr = MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2143   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
2144   ierr = MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2145   if (isseqdense) {
2146     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
2147   }
2148   if (reuse == MAT_INPLACE_MATRIX) {
2149     ierr = MatHeaderReplace(mat,&MT);CHKERRQ(ierr);
2150   } else if (reuse == MAT_INITIAL_MATRIX) {
2151     *M = MT;
2152   }
2153   PetscFunctionReturn(0);
2154 }
2155 
2156 /*@
2157     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
2158 
2159   Input Parameter:
2160 .  mat - the matrix (should be of type MATIS)
2161 .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
2162 
2163   Output Parameter:
2164 .  newmat - the matrix in AIJ format
2165 
2166   Level: developer
2167 
2168   Notes:
2169     This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface.
2170 
2171 .seealso: MATIS, MatConvert()
2172 @*/
2173 PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
2174 {
2175   PetscErrorCode ierr;
2176 
2177   PetscFunctionBegin;
2178   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2179   PetscValidLogicalCollectiveEnum(mat,reuse,2);
2180   PetscValidPointer(newmat,3);
2181   if (reuse == MAT_REUSE_MATRIX) {
2182     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
2183     PetscCheckSameComm(mat,1,*newmat,3);
2184     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
2185   }
2186   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));CHKERRQ(ierr);
2187   PetscFunctionReturn(0);
2188 }
2189 
2190 PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
2191 {
2192   PetscErrorCode ierr;
2193   Mat_IS         *matis = (Mat_IS*)(mat->data);
2194   PetscInt       rbs,cbs,m,n,M,N;
2195   Mat            B,localmat;
2196 
2197   PetscFunctionBegin;
2198   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
2199   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
2200   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
2201   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
2202   ierr = MatCreate(PetscObjectComm((PetscObject)mat),&B);CHKERRQ(ierr);
2203   ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr);
2204   ierr = MatSetBlockSize(B,rbs == cbs ? rbs : 1);CHKERRQ(ierr);
2205   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
2206   ierr = MatISSetLocalMatType(B,matis->lmattype);CHKERRQ(ierr);
2207   ierr = MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
2208   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
2209   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
2210   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
2211   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2212   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2213   *newmat = B;
2214   PetscFunctionReturn(0);
2215 }
2216 
2217 static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
2218 {
2219   PetscErrorCode ierr;
2220   Mat_IS         *matis = (Mat_IS*)A->data;
2221   PetscBool      local_sym;
2222 
2223   PetscFunctionBegin;
2224   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
2225   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2226   PetscFunctionReturn(0);
2227 }
2228 
2229 static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
2230 {
2231   PetscErrorCode ierr;
2232   Mat_IS         *matis = (Mat_IS*)A->data;
2233   PetscBool      local_sym;
2234 
2235   PetscFunctionBegin;
2236   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
2237   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2238   PetscFunctionReturn(0);
2239 }
2240 
2241 static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
2242 {
2243   PetscErrorCode ierr;
2244   Mat_IS         *matis = (Mat_IS*)A->data;
2245   PetscBool      local_sym;
2246 
2247   PetscFunctionBegin;
2248   if (A->rmap->mapping != A->cmap->mapping) {
2249     *flg = PETSC_FALSE;
2250     PetscFunctionReturn(0);
2251   }
2252   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
2253   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2254   PetscFunctionReturn(0);
2255 }
2256 
2257 static PetscErrorCode MatDestroy_IS(Mat A)
2258 {
2259   PetscErrorCode ierr;
2260   Mat_IS         *b = (Mat_IS*)A->data;
2261 
2262   PetscFunctionBegin;
2263   ierr = PetscFree(b->bdiag);CHKERRQ(ierr);
2264   ierr = PetscFree(b->lmattype);CHKERRQ(ierr);
2265   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
2266   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
2267   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
2268   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
2269   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
2270   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
2271   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
2272   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
2273   if (b->sf != b->csf) {
2274     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
2275     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
2276   } else b->csf = NULL;
2277   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
2278   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
2279   ierr = PetscFree(A->data);CHKERRQ(ierr);
2280   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
2281   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL);CHKERRQ(ierr);
2282   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
2283   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
2284   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
2285   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
2286   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr);
2287   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL);CHKERRQ(ierr);
2288   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL);CHKERRQ(ierr);
2289   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL);CHKERRQ(ierr);
2290   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL);CHKERRQ(ierr);
2291   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL);CHKERRQ(ierr);
2292   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL);CHKERRQ(ierr);
2293   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL);CHKERRQ(ierr);
2294   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL);CHKERRQ(ierr);
2295   PetscFunctionReturn(0);
2296 }
2297 
2298 static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
2299 {
2300   PetscErrorCode ierr;
2301   Mat_IS         *is  = (Mat_IS*)A->data;
2302   PetscScalar    zero = 0.0;
2303 
2304   PetscFunctionBegin;
2305   /*  scatter the global vector x into the local work vector */
2306   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2307   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2308 
2309   /* multiply the local matrix */
2310   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
2311 
2312   /* scatter product back into global memory */
2313   ierr = VecSet(y,zero);CHKERRQ(ierr);
2314   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2315   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2316   PetscFunctionReturn(0);
2317 }
2318 
2319 static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
2320 {
2321   Vec            temp_vec;
2322   PetscErrorCode ierr;
2323 
2324   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
2325   if (v3 != v2) {
2326     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
2327     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2328   } else {
2329     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2330     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
2331     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2332     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2333     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2334   }
2335   PetscFunctionReturn(0);
2336 }
2337 
2338 static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
2339 {
2340   Mat_IS         *is = (Mat_IS*)A->data;
2341   PetscErrorCode ierr;
2342 
2343   PetscFunctionBegin;
2344   /*  scatter the global vector x into the local work vector */
2345   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2346   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2347 
2348   /* multiply the local matrix */
2349   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
2350 
2351   /* scatter product back into global vector */
2352   ierr = VecSet(x,0);CHKERRQ(ierr);
2353   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2354   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2355   PetscFunctionReturn(0);
2356 }
2357 
2358 static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
2359 {
2360   Vec            temp_vec;
2361   PetscErrorCode ierr;
2362 
2363   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
2364   if (v3 != v2) {
2365     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
2366     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2367   } else {
2368     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2369     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
2370     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2371     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2372     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2373   }
2374   PetscFunctionReturn(0);
2375 }
2376 
2377 static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
2378 {
2379   Mat_IS         *a = (Mat_IS*)A->data;
2380   PetscErrorCode ierr;
2381   PetscViewer    sviewer;
2382   PetscBool      isascii,view = PETSC_TRUE;
2383 
2384   PetscFunctionBegin;
2385   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
2386   if (isascii)  {
2387     PetscViewerFormat format;
2388 
2389     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
2390     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
2391   }
2392   if (!view) PetscFunctionReturn(0);
2393   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
2394   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
2395   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
2396   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2397   PetscFunctionReturn(0);
2398 }
2399 
2400 static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values)
2401 {
2402   Mat_IS            *is = (Mat_IS*)mat->data;
2403   MPI_Datatype      nodeType;
2404   const PetscScalar *lv;
2405   PetscInt          bs;
2406   PetscErrorCode    ierr;
2407 
2408   PetscFunctionBegin;
2409   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
2410   ierr = MatSetBlockSize(is->A,bs);CHKERRQ(ierr);
2411   ierr = MatInvertBlockDiagonal(is->A,&lv);CHKERRQ(ierr);
2412   if (!is->bdiag) {
2413     ierr = PetscMalloc1(bs*mat->rmap->n,&is->bdiag);CHKERRQ(ierr);
2414   }
2415   ierr = MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType);CHKERRQ(ierr);
2416   ierr = MPI_Type_commit(&nodeType);CHKERRQ(ierr);
2417   ierr = PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr);
2418   ierr = PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr);
2419   ierr = MPI_Type_free(&nodeType);CHKERRQ(ierr);
2420   if (values) *values = is->bdiag;
2421   PetscFunctionReturn(0);
2422 }
2423 
2424 static PetscErrorCode MatISSetUpScatters_Private(Mat A)
2425 {
2426   Vec            cglobal,rglobal;
2427   IS             from;
2428   Mat_IS         *is = (Mat_IS*)A->data;
2429   PetscScalar    sum;
2430   const PetscInt *garray;
2431   PetscInt       nr,rbs,nc,cbs;
2432   PetscBool      iscuda;
2433   PetscErrorCode ierr;
2434 
2435   PetscFunctionBegin;
2436   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nr);CHKERRQ(ierr);
2437   ierr = ISLocalToGlobalMappingGetBlockSize(A->rmap->mapping,&rbs);CHKERRQ(ierr);
2438   ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&nc);CHKERRQ(ierr);
2439   ierr = ISLocalToGlobalMappingGetBlockSize(A->cmap->mapping,&cbs);CHKERRQ(ierr);
2440   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
2441   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
2442   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
2443   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
2444   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
2445   ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
2446   ierr = PetscObjectTypeCompare((PetscObject)is->y,VECSEQCUDA,&iscuda);CHKERRQ(ierr);
2447   if (iscuda) {
2448     ierr = PetscFree(A->defaultvectype);CHKERRQ(ierr);
2449     ierr = PetscStrallocpy(VECCUDA,&A->defaultvectype);CHKERRQ(ierr);
2450   }
2451   ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
2452   ierr = ISLocalToGlobalMappingGetBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr);
2453   ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
2454   ierr = VecScatterCreateWithData(rglobal,from,is->y,NULL,&is->rctx);CHKERRQ(ierr);
2455   ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr);
2456   ierr = ISDestroy(&from);CHKERRQ(ierr);
2457   if (A->rmap->mapping != A->cmap->mapping) {
2458     ierr = ISLocalToGlobalMappingGetBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr);
2459     ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
2460     ierr = VecScatterCreateWithData(cglobal,from,is->x,NULL,&is->cctx);CHKERRQ(ierr);
2461     ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr);
2462     ierr = ISDestroy(&from);CHKERRQ(ierr);
2463   } else {
2464     ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
2465     is->cctx = is->rctx;
2466   }
2467   ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
2468 
2469   /* interface counter vector (local) */
2470   ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
2471   ierr = VecSet(is->y,1.);CHKERRQ(ierr);
2472   ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2473   ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2474   ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2475   ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2476 
2477   /* special functions for block-diagonal matrices */
2478   ierr = VecSum(rglobal,&sum);CHKERRQ(ierr);
2479   if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && A->rmap->mapping == A->cmap->mapping) {
2480     A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS;
2481   } else {
2482     A->ops->invertblockdiagonal = NULL;
2483   }
2484   ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
2485 
2486   /* setup SF for general purpose shared indices based communications */
2487   ierr = MatISSetUpSF_IS(A);CHKERRQ(ierr);
2488   PetscFunctionReturn(0);
2489 }
2490 
2491 static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
2492 {
2493   PetscErrorCode ierr;
2494   PetscInt       nr,rbs,nc,cbs;
2495   Mat_IS         *is = (Mat_IS*)A->data;
2496 
2497   PetscFunctionBegin;
2498   PetscCheckSameComm(A,1,rmapping,2);
2499   PetscCheckSameComm(A,1,cmapping,3);
2500   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
2501   if (is->csf != is->sf) {
2502     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
2503     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
2504   } else is->csf = NULL;
2505   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
2506   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
2507   ierr = PetscFree(is->bdiag);CHKERRQ(ierr);
2508 
2509   /* Setup Layout and set local to global maps */
2510   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
2511   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
2512   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
2513   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
2514   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
2515   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
2516   /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */
2517   if (rmapping != cmapping && A->rmap->N == A->cmap->N) {
2518     PetscBool same,gsame;
2519 
2520     same = PETSC_FALSE;
2521     if (nr == nc && cbs == rbs) {
2522       const PetscInt *idxs1,*idxs2;
2523 
2524       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
2525       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
2526       ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr);
2527       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
2528       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
2529     }
2530     ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2531     if (gsame) cmapping = rmapping;
2532   }
2533   ierr = PetscLayoutSetBlockSize(A->rmap,rbs);CHKERRQ(ierr);
2534   ierr = PetscLayoutSetBlockSize(A->cmap,cbs);CHKERRQ(ierr);
2535   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
2536   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
2537 
2538   /* Create the local matrix A */
2539   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
2540   ierr = MatSetType(is->A,is->lmattype);CHKERRQ(ierr);
2541   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
2542   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
2543   ierr = MatSetOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
2544   ierr = MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
2545   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
2546   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
2547 
2548   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
2549     ierr = MatISSetUpScatters_Private(A);CHKERRQ(ierr);
2550   }
2551   ierr = MatSetUp(A);CHKERRQ(ierr);
2552   PetscFunctionReturn(0);
2553 }
2554 
2555 static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
2556 {
2557   Mat_IS         *is = (Mat_IS*)mat->data;
2558   PetscErrorCode ierr;
2559 #if defined(PETSC_USE_DEBUG)
2560   PetscInt       i,zm,zn;
2561 #endif
2562   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
2563 
2564   PetscFunctionBegin;
2565 #if defined(PETSC_USE_DEBUG)
2566   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
2567   /* count negative indices */
2568   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
2569   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
2570 #endif
2571   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
2572   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
2573 #if defined(PETSC_USE_DEBUG)
2574   /* count negative indices (should be the same as before) */
2575   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
2576   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2577   if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
2578   if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
2579 #endif
2580   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
2581   PetscFunctionReturn(0);
2582 }
2583 
2584 static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
2585 {
2586   Mat_IS         *is = (Mat_IS*)mat->data;
2587   PetscErrorCode ierr;
2588 #if defined(PETSC_USE_DEBUG)
2589   PetscInt       i,zm,zn;
2590 #endif
2591   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
2592 
2593   PetscFunctionBegin;
2594 #if defined(PETSC_USE_DEBUG)
2595   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
2596   /* count negative indices */
2597   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
2598   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
2599 #endif
2600   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
2601   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
2602 #if defined(PETSC_USE_DEBUG)
2603   /* count negative indices (should be the same as before) */
2604   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
2605   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2606   if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
2607   if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
2608 #endif
2609   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
2610   PetscFunctionReturn(0);
2611 }
2612 
2613 static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2614 {
2615   PetscErrorCode ierr;
2616   Mat_IS         *is = (Mat_IS*)A->data;
2617 
2618   PetscFunctionBegin;
2619   if (is->A->rmap->mapping) {
2620     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2621   } else {
2622     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2623   }
2624   PetscFunctionReturn(0);
2625 }
2626 
2627 static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2628 {
2629   PetscErrorCode ierr;
2630   Mat_IS         *is = (Mat_IS*)A->data;
2631 
2632   PetscFunctionBegin;
2633   if (is->A->rmap->mapping) {
2634 #if defined(PETSC_USE_DEBUG)
2635     PetscInt ibs,bs;
2636 
2637     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
2638     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
2639     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
2640 #endif
2641     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2642   } else {
2643     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2644   }
2645   PetscFunctionReturn(0);
2646 }
2647 
2648 static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2649 {
2650   Mat_IS         *is = (Mat_IS*)A->data;
2651   PetscErrorCode ierr;
2652 
2653   PetscFunctionBegin;
2654   if (!n) {
2655     is->pure_neumann = PETSC_TRUE;
2656   } else {
2657     PetscInt i;
2658     is->pure_neumann = PETSC_FALSE;
2659 
2660     if (columns) {
2661       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2662     } else {
2663       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2664     }
2665     if (diag != 0.) {
2666       const PetscScalar *array;
2667       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
2668       for (i=0; i<n; i++) {
2669         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
2670       }
2671       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
2672     }
2673     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2674     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2675   }
2676   PetscFunctionReturn(0);
2677 }
2678 
2679 static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
2680 {
2681   Mat_IS         *matis = (Mat_IS*)A->data;
2682   PetscInt       nr,nl,len,i;
2683   PetscInt       *lrows;
2684   PetscErrorCode ierr;
2685 
2686   PetscFunctionBegin;
2687 #if defined(PETSC_USE_DEBUG)
2688   if (columns || diag != 0. || (x && b)) {
2689     PetscBool cong;
2690 
2691     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
2692     cong = (PetscBool)(cong && matis->sf == matis->csf);
2693     if (!cong && columns) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Columns can be zeroed if and only if A->rmap and A->cmap are congruent and the l2g maps are the same for MATIS");
2694     if (!cong && diag != 0.) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Nonzero diagonal value supported if and only if A->rmap and A->cmap are congruent and the l2g maps are the same for MATIS");
2695     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent, and the l2g maps be the same");
2696   }
2697 #endif
2698   /* get locally owned rows */
2699   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
2700   /* fix right hand side if needed */
2701   if (x && b) {
2702     const PetscScalar *xx;
2703     PetscScalar       *bb;
2704 
2705     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
2706     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
2707     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
2708     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
2709     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
2710   }
2711   /* get rows associated to the local matrices */
2712   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
2713   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
2714   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
2715   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
2716   ierr = PetscFree(lrows);CHKERRQ(ierr);
2717   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
2718   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
2719   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
2720   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
2721   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
2722   ierr = PetscFree(lrows);CHKERRQ(ierr);
2723   PetscFunctionReturn(0);
2724 }
2725 
2726 static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2727 {
2728   PetscErrorCode ierr;
2729 
2730   PetscFunctionBegin;
2731   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
2732   PetscFunctionReturn(0);
2733 }
2734 
2735 static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2736 {
2737   PetscErrorCode ierr;
2738 
2739   PetscFunctionBegin;
2740   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
2741   PetscFunctionReturn(0);
2742 }
2743 
2744 static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2745 {
2746   Mat_IS         *is = (Mat_IS*)A->data;
2747   PetscErrorCode ierr;
2748 
2749   PetscFunctionBegin;
2750   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
2751   PetscFunctionReturn(0);
2752 }
2753 
2754 static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2755 {
2756   Mat_IS         *is = (Mat_IS*)A->data;
2757   PetscErrorCode ierr;
2758 
2759   PetscFunctionBegin;
2760   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
2761   /* fix for local empty rows/cols */
2762   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2763     Mat                    newlA;
2764     ISLocalToGlobalMapping rl2g,cl2g;
2765     IS                     nzr,nzc;
2766     PetscInt               nr,nc,nnzr,nnzc;
2767     PetscBool              lnewl2g,newl2g;
2768 
2769     ierr = MatGetSize(is->A,&nr,&nc);CHKERRQ(ierr);
2770     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr);CHKERRQ(ierr);
2771     if (!nzr) {
2772       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr);CHKERRQ(ierr);
2773     }
2774     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc);CHKERRQ(ierr);
2775     if (!nzc) {
2776       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc);CHKERRQ(ierr);
2777     }
2778     ierr = ISGetSize(nzr,&nnzr);CHKERRQ(ierr);
2779     ierr = ISGetSize(nzc,&nnzc);CHKERRQ(ierr);
2780     if (nnzr != nr || nnzc != nc) {
2781       ISLocalToGlobalMapping l2g;
2782       IS                     is1,is2;
2783 
2784       /* need new global l2g map */
2785       lnewl2g = PETSC_TRUE;
2786       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2787 
2788       /* extract valid submatrix */
2789       ierr = MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
2790 
2791       /* attach local l2g maps for successive calls of MatSetValues on the local matrix */
2792       ierr = ISLocalToGlobalMappingCreateIS(nzr,&l2g);CHKERRQ(ierr);
2793       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&is1);CHKERRQ(ierr);
2794       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2795       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
2796       if (is->A->rmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
2797         const PetscInt *idxs1,*idxs2;
2798         PetscInt       j,i,nl,*tidxs;
2799 
2800         ierr = ISLocalToGlobalMappingGetSize(is->A->rmap->mapping,&nl);CHKERRQ(ierr);
2801         ierr = ISLocalToGlobalMappingGetIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
2802         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
2803         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
2804         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
2805         if (j != nr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nr);
2806         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
2807         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
2808         ierr = ISDestroy(&is2);CHKERRQ(ierr);
2809         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->rmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
2810       }
2811       ierr = ISLocalToGlobalMappingCreateIS(is2,&rl2g);CHKERRQ(ierr);
2812       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2813       ierr = ISDestroy(&is2);CHKERRQ(ierr);
2814 
2815       ierr = ISLocalToGlobalMappingCreateIS(nzc,&l2g);CHKERRQ(ierr);
2816       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&is1);CHKERRQ(ierr);
2817       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2818       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
2819       if (is->A->cmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
2820         const PetscInt *idxs1,*idxs2;
2821         PetscInt       j,i,nl,*tidxs;
2822 
2823         ierr = ISLocalToGlobalMappingGetSize(is->A->cmap->mapping,&nl);CHKERRQ(ierr);
2824         ierr = ISLocalToGlobalMappingGetIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
2825         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
2826         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
2827         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
2828         if (j != nc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nc);
2829         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
2830         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
2831         ierr = ISDestroy(&is2);CHKERRQ(ierr);
2832         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->cmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
2833       }
2834       ierr = ISLocalToGlobalMappingCreateIS(is2,&cl2g);CHKERRQ(ierr);
2835       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2836       ierr = ISDestroy(&is2);CHKERRQ(ierr);
2837 
2838       ierr = MatSetLocalToGlobalMapping(newlA,rl2g,cl2g);CHKERRQ(ierr);
2839 
2840       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2841       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2842     } else { /* local matrix fully populated */
2843       lnewl2g = PETSC_FALSE;
2844       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2845       ierr    = PetscObjectReference((PetscObject)is->A);CHKERRQ(ierr);
2846       newlA   = is->A;
2847     }
2848     /* attach new global l2g map if needed */
2849     if (newl2g) {
2850       IS             gnzr,gnzc;
2851       const PetscInt *grid,*gcid;
2852 
2853       ierr = ISLocalToGlobalMappingApplyIS(A->rmap->mapping,nzr,&gnzr);CHKERRQ(ierr);
2854       ierr = ISLocalToGlobalMappingApplyIS(A->cmap->mapping,nzc,&gnzc);CHKERRQ(ierr);
2855       ierr = ISGetIndices(gnzr,&grid);CHKERRQ(ierr);
2856       ierr = ISGetIndices(gnzc,&gcid);CHKERRQ(ierr);
2857       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzr,grid,PETSC_COPY_VALUES,&rl2g);CHKERRQ(ierr);
2858       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzc,gcid,PETSC_COPY_VALUES,&cl2g);CHKERRQ(ierr);
2859       ierr = ISRestoreIndices(gnzr,&grid);CHKERRQ(ierr);
2860       ierr = ISRestoreIndices(gnzc,&gcid);CHKERRQ(ierr);
2861       ierr = ISDestroy(&gnzr);CHKERRQ(ierr);
2862       ierr = ISDestroy(&gnzc);CHKERRQ(ierr);
2863       ierr = MatSetLocalToGlobalMapping(A,rl2g,cl2g);CHKERRQ(ierr);
2864       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2865       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2866     }
2867     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
2868     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
2869     ierr = ISDestroy(&nzr);CHKERRQ(ierr);
2870     ierr = ISDestroy(&nzc);CHKERRQ(ierr);
2871     is->locempty = PETSC_FALSE;
2872   }
2873   PetscFunctionReturn(0);
2874 }
2875 
2876 static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2877 {
2878   Mat_IS *is = (Mat_IS*)mat->data;
2879 
2880   PetscFunctionBegin;
2881   *local = is->A;
2882   PetscFunctionReturn(0);
2883 }
2884 
2885 static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
2886 {
2887   PetscFunctionBegin;
2888   *local = NULL;
2889   PetscFunctionReturn(0);
2890 }
2891 
2892 /*@
2893     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2894 
2895   Input Parameter:
2896 .  mat - the matrix
2897 
2898   Output Parameter:
2899 .  local - the local matrix
2900 
2901   Level: advanced
2902 
2903   Notes:
2904     This can be called if you have precomputed the nonzero structure of the
2905   matrix and want to provide it to the inner matrix object to improve the performance
2906   of the MatSetValues() operation.
2907 
2908   Call MatISRestoreLocalMat() when finished with the local matrix.
2909 
2910 .seealso: MATIS
2911 @*/
2912 PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2913 {
2914   PetscErrorCode ierr;
2915 
2916   PetscFunctionBegin;
2917   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2918   PetscValidPointer(local,2);
2919   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
2920   PetscFunctionReturn(0);
2921 }
2922 
2923 /*@
2924     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
2925 
2926   Input Parameter:
2927 .  mat - the matrix
2928 
2929   Output Parameter:
2930 .  local - the local matrix
2931 
2932   Level: advanced
2933 
2934 .seealso: MATIS
2935 @*/
2936 PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
2937 {
2938   PetscErrorCode ierr;
2939 
2940   PetscFunctionBegin;
2941   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2942   PetscValidPointer(local,2);
2943   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
2944   PetscFunctionReturn(0);
2945 }
2946 
2947 static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype)
2948 {
2949   Mat_IS         *is = (Mat_IS*)mat->data;
2950   PetscErrorCode ierr;
2951 
2952   PetscFunctionBegin;
2953   if (is->A) {
2954     ierr = MatSetType(is->A,mtype);CHKERRQ(ierr);
2955   }
2956   ierr = PetscFree(is->lmattype);CHKERRQ(ierr);
2957   ierr = PetscStrallocpy(mtype,&is->lmattype);CHKERRQ(ierr);
2958   PetscFunctionReturn(0);
2959 }
2960 
2961 /*@
2962     MatISSetLocalMatType - Specifies the type of local matrix
2963 
2964   Input Parameter:
2965 .  mat - the matrix
2966 .  mtype - the local matrix type
2967 
2968   Output Parameter:
2969 
2970   Level: advanced
2971 
2972 .seealso: MATIS, MatSetType(), MatType
2973 @*/
2974 PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype)
2975 {
2976   PetscErrorCode ierr;
2977 
2978   PetscFunctionBegin;
2979   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2980   ierr = PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype));CHKERRQ(ierr);
2981   PetscFunctionReturn(0);
2982 }
2983 
2984 static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
2985 {
2986   Mat_IS         *is = (Mat_IS*)mat->data;
2987   PetscInt       nrows,ncols,orows,ocols;
2988   PetscErrorCode ierr;
2989   MatType        mtype,otype;
2990   PetscBool      sametype = PETSC_TRUE;
2991 
2992   PetscFunctionBegin;
2993   if (is->A) {
2994     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
2995     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2996     if (orows != nrows || ocols != ncols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %Dx%D (you passed a %Dx%D matrix)",orows,ocols,nrows,ncols);
2997     ierr = MatGetType(local,&mtype);CHKERRQ(ierr);
2998     ierr = MatGetType(is->A,&otype);CHKERRQ(ierr);
2999     ierr = PetscStrcmp(mtype,otype,&sametype);CHKERRQ(ierr);
3000   }
3001   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
3002   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
3003   is->A = local;
3004   ierr  = MatGetType(is->A,&mtype);CHKERRQ(ierr);
3005   ierr  = MatISSetLocalMatType(mat,mtype);CHKERRQ(ierr);
3006   if (!sametype && !is->islocalref) {
3007     ierr = MatISSetUpScatters_Private(mat);CHKERRQ(ierr);
3008   }
3009   PetscFunctionReturn(0);
3010 }
3011 
3012 /*@
3013     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
3014 
3015   Collective on Mat
3016 
3017   Input Parameter:
3018 .  mat - the matrix
3019 .  local - the local matrix
3020 
3021   Output Parameter:
3022 
3023   Level: advanced
3024 
3025   Notes:
3026     This can be called if you have precomputed the local matrix and
3027   want to provide it to the matrix object MATIS.
3028 
3029 .seealso: MATIS
3030 @*/
3031 PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
3032 {
3033   PetscErrorCode ierr;
3034 
3035   PetscFunctionBegin;
3036   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3037   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
3038   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
3039   PetscFunctionReturn(0);
3040 }
3041 
3042 static PetscErrorCode MatZeroEntries_IS(Mat A)
3043 {
3044   Mat_IS         *a = (Mat_IS*)A->data;
3045   PetscErrorCode ierr;
3046 
3047   PetscFunctionBegin;
3048   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
3049   PetscFunctionReturn(0);
3050 }
3051 
3052 static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
3053 {
3054   Mat_IS         *is = (Mat_IS*)A->data;
3055   PetscErrorCode ierr;
3056 
3057   PetscFunctionBegin;
3058   ierr = MatScale(is->A,a);CHKERRQ(ierr);
3059   PetscFunctionReturn(0);
3060 }
3061 
3062 static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
3063 {
3064   Mat_IS         *is = (Mat_IS*)A->data;
3065   PetscErrorCode ierr;
3066 
3067   PetscFunctionBegin;
3068   /* get diagonal of the local matrix */
3069   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
3070 
3071   /* scatter diagonal back into global vector */
3072   ierr = VecSet(v,0);CHKERRQ(ierr);
3073   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3074   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3075   PetscFunctionReturn(0);
3076 }
3077 
3078 static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
3079 {
3080   Mat_IS         *a = (Mat_IS*)A->data;
3081   PetscErrorCode ierr;
3082 
3083   PetscFunctionBegin;
3084   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
3085   PetscFunctionReturn(0);
3086 }
3087 
3088 static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
3089 {
3090   Mat_IS         *y = (Mat_IS*)Y->data;
3091   Mat_IS         *x;
3092 #if defined(PETSC_USE_DEBUG)
3093   PetscBool      ismatis;
3094 #endif
3095   PetscErrorCode ierr;
3096 
3097   PetscFunctionBegin;
3098 #if defined(PETSC_USE_DEBUG)
3099   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
3100   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
3101 #endif
3102   x = (Mat_IS*)X->data;
3103   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
3104   PetscFunctionReturn(0);
3105 }
3106 
3107 static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
3108 {
3109   Mat                    lA;
3110   Mat_IS                 *matis;
3111   ISLocalToGlobalMapping rl2g,cl2g;
3112   IS                     is;
3113   const PetscInt         *rg,*rl;
3114   PetscInt               nrg;
3115   PetscInt               N,M,nrl,i,*idxs;
3116   PetscErrorCode         ierr;
3117 
3118   PetscFunctionBegin;
3119   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3120   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
3121   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
3122   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
3123 #if defined(PETSC_USE_DEBUG)
3124   for (i=0;i<nrl;i++) if (rl[i]>=nrg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row index %D -> %D greater then maximum possible %D",i,rl[i],nrg);
3125 #endif
3126   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
3127   /* map from [0,nrl) to row */
3128   for (i=0;i<nrl;i++) idxs[i] = rl[i];
3129   for (i=nrl;i<nrg;i++) idxs[i] = -1;
3130   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
3131   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3132   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3133   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
3134   ierr = ISDestroy(&is);CHKERRQ(ierr);
3135   /* compute new l2g map for columns */
3136   if (col != row || A->rmap->mapping != A->cmap->mapping) {
3137     const PetscInt *cg,*cl;
3138     PetscInt       ncg;
3139     PetscInt       ncl;
3140 
3141     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3142     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
3143     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
3144     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
3145 #if defined(PETSC_USE_DEBUG)
3146     for (i=0;i<ncl;i++) if (cl[i]>=ncg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local column index %D -> %D greater then maximum possible %D",i,cl[i],ncg);
3147 #endif
3148     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
3149     /* map from [0,ncl) to col */
3150     for (i=0;i<ncl;i++) idxs[i] = cl[i];
3151     for (i=ncl;i<ncg;i++) idxs[i] = -1;
3152     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
3153     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3154     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3155     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
3156     ierr = ISDestroy(&is);CHKERRQ(ierr);
3157   } else {
3158     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
3159     cl2g = rl2g;
3160   }
3161   /* create the MATIS submatrix */
3162   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
3163   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
3164   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
3165   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
3166   matis = (Mat_IS*)((*submat)->data);
3167   matis->islocalref = PETSC_TRUE;
3168   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
3169   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
3170   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
3171   ierr = MatSetUp(*submat);CHKERRQ(ierr);
3172   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3173   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3174   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3175   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3176   /* remove unsupported ops */
3177   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3178   (*submat)->ops->destroy               = MatDestroy_IS;
3179   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
3180   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
3181   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
3182   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
3183   PetscFunctionReturn(0);
3184 }
3185 
3186 static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
3187 {
3188   Mat_IS         *a = (Mat_IS*)A->data;
3189   char           type[256];
3190   PetscBool      flg;
3191   PetscErrorCode ierr;
3192 
3193   PetscFunctionBegin;
3194   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
3195   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
3196   ierr = PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL);CHKERRQ(ierr);
3197   ierr = PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg);CHKERRQ(ierr);
3198   if (flg) {
3199     ierr = MatISSetLocalMatType(A,type);CHKERRQ(ierr);
3200   }
3201   if (a->A) {
3202     ierr = MatSetFromOptions(a->A);CHKERRQ(ierr);
3203   }
3204   ierr = PetscOptionsTail();CHKERRQ(ierr);
3205   PetscFunctionReturn(0);
3206 }
3207 
3208 /*@
3209     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
3210        process but not across processes.
3211 
3212    Input Parameters:
3213 +     comm    - MPI communicator that will share the matrix
3214 .     bs      - block size of the matrix
3215 .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
3216 .     rmap    - local to global map for rows
3217 -     cmap    - local to global map for cols
3218 
3219    Output Parameter:
3220 .    A - the resulting matrix
3221 
3222    Level: advanced
3223 
3224    Notes:
3225     See MATIS for more details.
3226           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
3227           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
3228           If either rmap or cmap are NULL, then the matrix is assumed to be square.
3229 
3230 .seealso: MATIS, MatSetLocalToGlobalMapping()
3231 @*/
3232 PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
3233 {
3234   PetscErrorCode ierr;
3235 
3236   PetscFunctionBegin;
3237   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
3238   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3239   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
3240   if (bs > 0) {
3241     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
3242   }
3243   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
3244   if (rmap && cmap) {
3245     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
3246   } else if (!rmap) {
3247     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
3248   } else {
3249     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
3250   }
3251   PetscFunctionReturn(0);
3252 }
3253 
3254 /*MC
3255    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
3256    This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector
3257    product is handled "implicitly".
3258 
3259    Options Database Keys:
3260 + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
3261 . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
3262 - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
3263 
3264    Notes:
3265     Options prefix for the inner matrix are given by -is_mat_xxx
3266 
3267           You must call MatSetLocalToGlobalMapping() before using this matrix type.
3268 
3269           You can do matrix preallocation on the local matrix after you obtain it with
3270           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
3271 
3272   Level: advanced
3273 
3274 .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
3275 
3276 M*/
3277 
3278 PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
3279 {
3280   PetscErrorCode ierr;
3281   Mat_IS         *b;
3282 
3283   PetscFunctionBegin;
3284   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
3285   ierr    = PetscStrallocpy(MATAIJ,&b->lmattype);CHKERRQ(ierr);
3286   A->data = (void*)b;
3287 
3288   /* matrix ops */
3289   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3290   A->ops->mult                    = MatMult_IS;
3291   A->ops->multadd                 = MatMultAdd_IS;
3292   A->ops->multtranspose           = MatMultTranspose_IS;
3293   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
3294   A->ops->destroy                 = MatDestroy_IS;
3295   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
3296   A->ops->setvalues               = MatSetValues_IS;
3297   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
3298   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
3299   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
3300   A->ops->zerorows                = MatZeroRows_IS;
3301   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
3302   A->ops->assemblybegin           = MatAssemblyBegin_IS;
3303   A->ops->assemblyend             = MatAssemblyEnd_IS;
3304   A->ops->view                    = MatView_IS;
3305   A->ops->zeroentries             = MatZeroEntries_IS;
3306   A->ops->scale                   = MatScale_IS;
3307   A->ops->getdiagonal             = MatGetDiagonal_IS;
3308   A->ops->setoption               = MatSetOption_IS;
3309   A->ops->ishermitian             = MatIsHermitian_IS;
3310   A->ops->issymmetric             = MatIsSymmetric_IS;
3311   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
3312   A->ops->duplicate               = MatDuplicate_IS;
3313   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
3314   A->ops->copy                    = MatCopy_IS;
3315   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
3316   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
3317   A->ops->axpy                    = MatAXPY_IS;
3318   A->ops->diagonalset             = MatDiagonalSet_IS;
3319   A->ops->shift                   = MatShift_IS;
3320   A->ops->transpose               = MatTranspose_IS;
3321   A->ops->getinfo                 = MatGetInfo_IS;
3322   A->ops->diagonalscale           = MatDiagonalScale_IS;
3323   A->ops->setfromoptions          = MatSetFromOptions_IS;
3324 
3325   /* special MATIS functions */
3326   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS);CHKERRQ(ierr);
3327   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
3328   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
3329   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
3330   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3331   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
3332   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS);CHKERRQ(ierr);
3333   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS);CHKERRQ(ierr);
3334   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3335   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3336   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3337   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3338   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3339   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3340   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3341   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
3342   PetscFunctionReturn(0);
3343 }
3344