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