xref: /petsc/src/mat/impls/is/matis.c (revision 6bdc912d96595d6bc6aa6d7c9bd9eea28bbb5423)
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 <../src/mat/impls/aij/mpi/mpiaij.h>
12 #include <petsc/private/sfimpl.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 
18 static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
19 {
20   MatISLocalFields lf = (MatISLocalFields)ptr;
21   PetscInt         i;
22   PetscErrorCode   ierr;
23 
24   PetscFunctionBegin;
25   for (i=0;i<lf->nr;i++) {
26     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
27   }
28   for (i=0;i<lf->nc;i++) {
29     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
30   }
31   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
32   ierr = PetscFree(lf);CHKERRQ(ierr);
33   PetscFunctionReturn(0);
34 }
35 
36 static PetscErrorCode MatISContainerDestroyArray_Private(void *ptr)
37 {
38   PetscErrorCode ierr;
39 
40   PetscFunctionBeginUser;
41   ierr = PetscFree(ptr);CHKERRQ(ierr);
42   PetscFunctionReturn(0);
43 }
44 
45 PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
46 {
47   Mat_MPIAIJ             *aij  = (Mat_MPIAIJ*)A->data;
48   Mat_SeqAIJ             *diag = (Mat_SeqAIJ*)(aij->A->data);
49   Mat_SeqAIJ             *offd = (Mat_SeqAIJ*)(aij->B->data);
50   Mat                    lA;
51   ISLocalToGlobalMapping rl2g,cl2g;
52   IS                     is;
53   MPI_Comm               comm;
54   void                   *ptrs[2];
55   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
56   PetscScalar            *dd,*od,*aa,*data;
57   PetscInt               *di,*dj,*oi,*oj;
58   PetscInt               *aux,*ii,*jj;
59   PetscInt               lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
60   PetscErrorCode         ierr;
61 
62   PetscFunctionBegin;
63   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
64   if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present");
65 
66   /* access relevant information from MPIAIJ */
67   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
68   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
69   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
70   di   = diag->i;
71   dj   = diag->j;
72   dd   = diag->a;
73   oc   = aij->B->cmap->n;
74   oi   = offd->i;
75   oj   = offd->j;
76   od   = offd->a;
77   nnz  = diag->i[dr] + offd->i[dr];
78 
79   /* generate l2g maps for rows and cols */
80   ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
81   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
82   ierr = ISDestroy(&is);CHKERRQ(ierr);
83   if (dr) {
84     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
85     for (i=0; i<dc; i++) aux[i]    = i+stc;
86     for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i];
87     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
88     lc   = dc+oc;
89   } else {
90     ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
91     lc   = 0;
92   }
93   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
94   ierr = ISDestroy(&is);CHKERRQ(ierr);
95 
96   /* create MATIS object */
97   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
98   ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
99   ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
100   ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
101   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
102   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
103 
104   /* merge local matrices */
105   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
106   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
107   ii   = aux;
108   jj   = aux+dr+1;
109   aa   = data;
110   *ii  = *(di++) + *(oi++);
111   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
112   {
113      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
114      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
115      *(++ii) = *(di++) + *(oi++);
116   }
117   for (;cum<dr;cum++) *(++ii) = nnz;
118   ii   = aux;
119   jj   = aux+dr+1;
120   aa   = data;
121   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
122 
123   /* create containers to destroy the data */
124   ptrs[0] = aux;
125   ptrs[1] = data;
126   for (i=0; i<2; i++) {
127     PetscContainer c;
128 
129     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
130     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
131     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyArray_Private);CHKERRQ(ierr);
132     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
133     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
134   }
135 
136   /* finalize matrix */
137   ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
138   ierr = MatDestroy(&lA);CHKERRQ(ierr);
139   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
140   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
141   PetscFunctionReturn(0);
142 }
143 
144 /*@
145    MatISSetUpSF - Setup star forest objects used by MatIS.
146 
147    Collective on MPI_Comm
148 
149    Input Parameters:
150 +  A - the matrix
151 
152    Level: advanced
153 
154    Notes: This function does not need to be called by the user.
155 
156 .keywords: matrix
157 
158 .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
159 @*/
160 PetscErrorCode  MatISSetUpSF(Mat A)
161 {
162   PetscErrorCode ierr;
163 
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
166   PetscValidType(A,1);
167   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
168   PetscFunctionReturn(0);
169 }
170 
171 PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
172 {
173   Mat                    **nest,*snest,**rnest,lA,B;
174   IS                     *iscol,*isrow,*islrow,*islcol;
175   ISLocalToGlobalMapping rl2g,cl2g;
176   MPI_Comm               comm;
177   PetscInt               *lr,*lc,*l2gidxs;
178   PetscInt               i,j,nr,nc,rbs,cbs;
179   PetscBool              convert,lreuse,*istrans;
180   PetscErrorCode         ierr;
181 
182   PetscFunctionBegin;
183   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
184   lreuse = PETSC_FALSE;
185   rnest  = NULL;
186   if (reuse == MAT_REUSE_MATRIX) {
187     PetscBool ismatis,isnest;
188 
189     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
190     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
191     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
192     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
193     if (isnest) {
194       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
195       lreuse = (PetscBool)(i == nr && j == nc);
196       if (!lreuse) rnest = NULL;
197     }
198   }
199   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
200   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
201   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
202                       nr,&islrow,nc,&islcol,
203                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
204   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
205   for (i=0;i<nr;i++) {
206     for (j=0;j<nc;j++) {
207       PetscBool ismatis;
208       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
209 
210       /* Null matrix pointers are allowed in MATNEST */
211       if (!nest[i][j]) continue;
212 
213       /* Nested matrices should be of type MATIS */
214       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
215       if (istrans[ij]) {
216         Mat T,lT;
217         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
218         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
219         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);
220         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
221         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
222       } else {
223         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
224         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) is not of type MATIS",i,j);
225         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
226       }
227 
228       /* Check compatibility of local sizes */
229       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
230       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
231       if (!l1 || !l2) continue;
232       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);
233       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);
234       lr[i] = l1;
235       lc[j] = l2;
236 
237       /* check compatibilty for local matrix reusage */
238       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
239     }
240   }
241 
242 #if defined (PETSC_USE_DEBUG)
243   /* Check compatibility of l2g maps for rows */
244   for (i=0;i<nr;i++) {
245     rl2g = NULL;
246     for (j=0;j<nc;j++) {
247       PetscInt n1,n2;
248 
249       if (!nest[i][j]) continue;
250       if (istrans[i*nc+j]) {
251         Mat T;
252 
253         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
254         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
255       } else {
256         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
257       }
258       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
259       if (!n1) continue;
260       if (!rl2g) {
261         rl2g = cl2g;
262       } else {
263         const PetscInt *idxs1,*idxs2;
264         PetscBool      same;
265 
266         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
267         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);
268         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
269         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
270         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
271         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
272         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
273         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);
274       }
275     }
276   }
277   /* Check compatibility of l2g maps for columns */
278   for (i=0;i<nc;i++) {
279     rl2g = NULL;
280     for (j=0;j<nr;j++) {
281       PetscInt n1,n2;
282 
283       if (!nest[j][i]) continue;
284       if (istrans[j*nc+i]) {
285         Mat T;
286 
287         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
288         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
289       } else {
290         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
291       }
292       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
293       if (!n1) continue;
294       if (!rl2g) {
295         rl2g = cl2g;
296       } else {
297         const PetscInt *idxs1,*idxs2;
298         PetscBool      same;
299 
300         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
301         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);
302         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
303         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
304         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
305         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
306         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
307         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);
308       }
309     }
310   }
311 #endif
312 
313   B = NULL;
314   if (reuse != MAT_REUSE_MATRIX) {
315     PetscInt stl;
316 
317     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
318     for (i=0,stl=0;i<nr;i++) stl += lr[i];
319     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
320     for (i=0,stl=0;i<nr;i++) {
321       Mat            usedmat;
322       Mat_IS         *matis;
323       const PetscInt *idxs;
324 
325       /* local IS for local NEST */
326       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
327 
328       /* l2gmap */
329       j = 0;
330       usedmat = nest[i][j];
331       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
332       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
333 
334       if (istrans[i*nc+j]) {
335         Mat T;
336         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
337         usedmat = T;
338       }
339       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
340       matis = (Mat_IS*)(usedmat->data);
341       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
342       if (istrans[i*nc+j]) {
343         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
344         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
345       } else {
346         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
347         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
348       }
349       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
350       stl += lr[i];
351     }
352     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
353 
354     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
355     for (i=0,stl=0;i<nc;i++) stl += lc[i];
356     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
357     for (i=0,stl=0;i<nc;i++) {
358       Mat            usedmat;
359       Mat_IS         *matis;
360       const PetscInt *idxs;
361 
362       /* local IS for local NEST */
363       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
364 
365       /* l2gmap */
366       j = 0;
367       usedmat = nest[j][i];
368       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
369       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
370       if (istrans[j*nc+i]) {
371         Mat T;
372         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
373         usedmat = T;
374       }
375       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
376       matis = (Mat_IS*)(usedmat->data);
377       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
378       if (istrans[j*nc+i]) {
379         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
380         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
381       } else {
382         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
383         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
384       }
385       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
386       stl += lc[i];
387     }
388     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
389 
390     /* Create MATIS */
391     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
392     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
393     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
394     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
395     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
396     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
397     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
398     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
399     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
400     for (i=0;i<nr*nc;i++) {
401       if (istrans[i]) {
402         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
403       }
404     }
405     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
406     ierr = MatDestroy(&lA);CHKERRQ(ierr);
407     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
408     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
409     if (reuse == MAT_INPLACE_MATRIX) {
410       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
411     } else {
412       *newmat = B;
413     }
414   } else {
415     if (lreuse) {
416       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
417       for (i=0;i<nr;i++) {
418         for (j=0;j<nc;j++) {
419           if (snest[i*nc+j]) {
420             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
421             if (istrans[i*nc+j]) {
422               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
423             }
424           }
425         }
426       }
427     } else {
428       PetscInt stl;
429       for (i=0,stl=0;i<nr;i++) {
430         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
431         stl  += lr[i];
432       }
433       for (i=0,stl=0;i<nc;i++) {
434         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
435         stl  += lc[i];
436       }
437       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
438       for (i=0;i<nr*nc;i++) {
439         if (istrans[i]) {
440           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
441         }
442       }
443       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
444       ierr = MatDestroy(&lA);CHKERRQ(ierr);
445     }
446     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
447     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
448   }
449 
450   /* Create local matrix in MATNEST format */
451   convert = PETSC_FALSE;
452   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
453   if (convert) {
454     Mat              M;
455     MatISLocalFields lf;
456     PetscContainer   c;
457 
458     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
459     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
460     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
461     ierr = MatDestroy(&M);CHKERRQ(ierr);
462 
463     /* attach local fields to the matrix */
464     ierr = PetscNew(&lf);CHKERRQ(ierr);
465     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
466     for (i=0;i<nr;i++) {
467       PetscInt n,st;
468 
469       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
470       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
471       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
472     }
473     for (i=0;i<nc;i++) {
474       PetscInt n,st;
475 
476       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
477       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
478       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
479     }
480     lf->nr = nr;
481     lf->nc = nc;
482     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
483     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
484     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
485     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
486     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
487   }
488 
489   /* Free workspace */
490   for (i=0;i<nr;i++) {
491     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
492   }
493   for (i=0;i<nc;i++) {
494     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
495   }
496   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
497   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
498   PetscFunctionReturn(0);
499 }
500 
501 static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
502 {
503   Mat_IS            *matis = (Mat_IS*)A->data;
504   Vec               ll,rr;
505   const PetscScalar *Y,*X;
506   PetscScalar       *x,*y;
507   PetscErrorCode    ierr;
508 
509   PetscFunctionBegin;
510   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
511   if (l) {
512     ll   = matis->y;
513     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
514     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
515     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
516   } else {
517     ll = NULL;
518   }
519   if (r) {
520     rr   = matis->x;
521     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
522     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
523     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
524   } else {
525     rr = NULL;
526   }
527   if (ll) {
528     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
529     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
530     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
531   }
532   if (rr) {
533     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
534     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
535     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
536   }
537   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
538   PetscFunctionReturn(0);
539 }
540 
541 static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
542 {
543   Mat_IS         *matis = (Mat_IS*)A->data;
544   MatInfo        info;
545   PetscReal      isend[6],irecv[6];
546   PetscInt       bs;
547   PetscErrorCode ierr;
548 
549   PetscFunctionBegin;
550   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
551   if (matis->A->ops->getinfo) {
552     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
553     isend[0] = info.nz_used;
554     isend[1] = info.nz_allocated;
555     isend[2] = info.nz_unneeded;
556     isend[3] = info.memory;
557     isend[4] = info.mallocs;
558   } else {
559     isend[0] = 0.;
560     isend[1] = 0.;
561     isend[2] = 0.;
562     isend[3] = 0.;
563     isend[4] = 0.;
564   }
565   isend[5] = matis->A->num_ass;
566   if (flag == MAT_LOCAL) {
567     ginfo->nz_used      = isend[0];
568     ginfo->nz_allocated = isend[1];
569     ginfo->nz_unneeded  = isend[2];
570     ginfo->memory       = isend[3];
571     ginfo->mallocs      = isend[4];
572     ginfo->assemblies   = isend[5];
573   } else if (flag == MAT_GLOBAL_MAX) {
574     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
575 
576     ginfo->nz_used      = irecv[0];
577     ginfo->nz_allocated = irecv[1];
578     ginfo->nz_unneeded  = irecv[2];
579     ginfo->memory       = irecv[3];
580     ginfo->mallocs      = irecv[4];
581     ginfo->assemblies   = irecv[5];
582   } else if (flag == MAT_GLOBAL_SUM) {
583     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
584 
585     ginfo->nz_used      = irecv[0];
586     ginfo->nz_allocated = irecv[1];
587     ginfo->nz_unneeded  = irecv[2];
588     ginfo->memory       = irecv[3];
589     ginfo->mallocs      = irecv[4];
590     ginfo->assemblies   = A->num_ass;
591   }
592   ginfo->block_size        = bs;
593   ginfo->fill_ratio_given  = 0;
594   ginfo->fill_ratio_needed = 0;
595   ginfo->factor_mallocs    = 0;
596   PetscFunctionReturn(0);
597 }
598 
599 PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
600 {
601   Mat                    C,lC,lA;
602   PetscErrorCode         ierr;
603 
604   PetscFunctionBegin;
605   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
606     ISLocalToGlobalMapping rl2g,cl2g;
607     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
608     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
609     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
610     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
611     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
612     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
613   } else {
614     C = *B;
615   }
616 
617   /* perform local transposition */
618   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
619   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
620   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
621   ierr = MatDestroy(&lC);CHKERRQ(ierr);
622 
623   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
624     *B = C;
625   } else {
626     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
627   }
628   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
629   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
630   PetscFunctionReturn(0);
631 }
632 
633 PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
634 {
635   Mat_IS         *is = (Mat_IS*)A->data;
636   PetscErrorCode ierr;
637 
638   PetscFunctionBegin;
639   if (D) { /* MatShift_IS pass D = NULL */
640     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
641     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
642   }
643   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
644   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
645   PetscFunctionReturn(0);
646 }
647 
648 PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
649 {
650   Mat_IS         *is = (Mat_IS*)A->data;
651   PetscErrorCode ierr;
652 
653   PetscFunctionBegin;
654   ierr = VecSet(is->y,a);CHKERRQ(ierr);
655   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
656   PetscFunctionReturn(0);
657 }
658 
659 static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
660 {
661   PetscErrorCode ierr;
662   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
663 
664   PetscFunctionBegin;
665 #if defined(PETSC_USE_DEBUG)
666   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);
667 #endif
668   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
669   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
670   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
671   PetscFunctionReturn(0);
672 }
673 
674 static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
675 {
676   PetscErrorCode ierr;
677   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
678 
679   PetscFunctionBegin;
680 #if defined(PETSC_USE_DEBUG)
681   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);
682 #endif
683   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
684   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
685   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
686   PetscFunctionReturn(0);
687 }
688 
689 static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
690 {
691   PetscInt      *owners = map->range;
692   PetscInt       n      = map->n;
693   PetscSF        sf;
694   PetscInt      *lidxs,*work = NULL;
695   PetscSFNode   *ridxs;
696   PetscMPIInt    rank;
697   PetscInt       r, p = 0, len = 0;
698   PetscErrorCode ierr;
699 
700   PetscFunctionBegin;
701   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
702   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
703   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
704   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
705   for (r = 0; r < n; ++r) lidxs[r] = -1;
706   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
707   for (r = 0; r < N; ++r) {
708     const PetscInt idx = idxs[r];
709     if (idx < 0 || map->N <= idx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index %D out of range [0,%D)",idx,map->N);
710     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
711       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
712     }
713     ridxs[r].rank = p;
714     ridxs[r].index = idxs[r] - owners[p];
715   }
716   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
717   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
718   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
719   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
720   if (ogidxs) { /* communicate global idxs */
721     PetscInt cum = 0,start,*work2;
722 
723     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
724     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
725     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
726     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
727     start -= cum;
728     cum = 0;
729     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
730     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
731     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
732     ierr = PetscFree(work2);CHKERRQ(ierr);
733   }
734   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
735   /* Compress and put in indices */
736   for (r = 0; r < n; ++r)
737     if (lidxs[r] >= 0) {
738       if (work) work[len] = work[r];
739       lidxs[len++] = r;
740     }
741   if (on) *on = len;
742   if (oidxs) *oidxs = lidxs;
743   if (ogidxs) *ogidxs = work;
744   PetscFunctionReturn(0);
745 }
746 
747 static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
748 {
749   Mat               locmat,newlocmat;
750   Mat_IS            *newmatis;
751 #if defined(PETSC_USE_DEBUG)
752   Vec               rtest,ltest;
753   const PetscScalar *array;
754 #endif
755   const PetscInt    *idxs;
756   PetscInt          i,m,n;
757   PetscErrorCode    ierr;
758 
759   PetscFunctionBegin;
760   if (scall == MAT_REUSE_MATRIX) {
761     PetscBool ismatis;
762 
763     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
764     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
765     newmatis = (Mat_IS*)(*newmat)->data;
766     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
767     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
768   }
769   /* irow and icol may not have duplicate entries */
770 #if defined(PETSC_USE_DEBUG)
771   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
772   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
773   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
774   for (i=0;i<n;i++) {
775     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
776   }
777   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
778   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
779   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
780   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
781   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
782   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]));
783   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
784   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
785   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
786   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
787   for (i=0;i<n;i++) {
788     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
789   }
790   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
791   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
792   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
793   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
794   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
795   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]));
796   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
797   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
798   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
799   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
800 #endif
801   if (scall == MAT_INITIAL_MATRIX) {
802     Mat_IS                 *matis = (Mat_IS*)mat->data;
803     ISLocalToGlobalMapping rl2g;
804     IS                     is;
805     PetscInt               *lidxs,*lgidxs,*newgidxs;
806     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
807     MPI_Comm               comm;
808 
809     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
810     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
811     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
812     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
813     rbs  = arbs == irbs ? irbs : 1;
814     cbs  = acbs == icbs ? icbs : 1;
815     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
816     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
817     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
818     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
819     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
820     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
821     /* communicate irow to their owners in the layout */
822     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
823     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
824     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
825     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
826     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
827     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
828     ierr = PetscFree(lidxs);CHKERRQ(ierr);
829     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
830     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
831     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
832     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
833     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
834     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
835     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
836       if (matis->sf_leafdata[i]) {
837         lidxs[newloc] = i;
838         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
839       }
840     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
841     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
842     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
843     ierr = ISDestroy(&is);CHKERRQ(ierr);
844     /* local is to extract local submatrix */
845     newmatis = (Mat_IS*)(*newmat)->data;
846     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
847     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
848       PetscBool cong;
849 
850       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
851       if (cong) mat->congruentlayouts = 1;
852       else      mat->congruentlayouts = 0;
853     }
854     if (mat->congruentlayouts && irow == icol && matis->csf == matis->sf) {
855       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
856       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
857       newmatis->getsub_cis = newmatis->getsub_ris;
858     } else {
859       ISLocalToGlobalMapping cl2g;
860 
861       /* communicate icol to their owners in the layout */
862       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
863       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
864       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
865       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
866       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
867       ierr = PetscFree(lidxs);CHKERRQ(ierr);
868       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
869       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
870       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
871       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
872       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
873       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
874       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
875         if (matis->csf_leafdata[i]) {
876           lidxs[newloc] = i;
877           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
878         }
879       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
880       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
881       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
882       ierr = ISDestroy(&is);CHKERRQ(ierr);
883       /* local is to extract local submatrix */
884       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
885       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
886       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
887     }
888     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
889   } else {
890     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
891   }
892   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
893   newmatis = (Mat_IS*)(*newmat)->data;
894   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
895   if (scall == MAT_INITIAL_MATRIX) {
896     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
897     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
898   }
899   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
900   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
901   PetscFunctionReturn(0);
902 }
903 
904 static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
905 {
906   Mat_IS         *a = (Mat_IS*)A->data,*b;
907   PetscBool      ismatis;
908   PetscErrorCode ierr;
909 
910   PetscFunctionBegin;
911   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
912   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
913   b = (Mat_IS*)B->data;
914   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
915   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
916   PetscFunctionReturn(0);
917 }
918 
919 static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
920 {
921   Vec               v;
922   const PetscScalar *array;
923   PetscInt          i,n;
924   PetscErrorCode    ierr;
925 
926   PetscFunctionBegin;
927   *missing = PETSC_FALSE;
928   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
929   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
930   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
931   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
932   for (i=0;i<n;i++) if (array[i] == 0.) break;
933   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
934   ierr = VecDestroy(&v);CHKERRQ(ierr);
935   if (i != n) *missing = PETSC_TRUE;
936   if (d) {
937     *d = -1;
938     if (*missing) {
939       PetscInt rstart;
940       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
941       *d = i+rstart;
942     }
943   }
944   PetscFunctionReturn(0);
945 }
946 
947 static PetscErrorCode MatISSetUpSF_IS(Mat B)
948 {
949   Mat_IS         *matis = (Mat_IS*)(B->data);
950   const PetscInt *gidxs;
951   PetscInt       nleaves;
952   PetscErrorCode ierr;
953 
954   PetscFunctionBegin;
955   if (matis->sf) PetscFunctionReturn(0);
956   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
957   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
958   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
959   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
960   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
961   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
962   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
963     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
964     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
965     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
966     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
967     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
968     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
969   } else {
970     matis->csf = matis->sf;
971     matis->csf_leafdata = matis->sf_leafdata;
972     matis->csf_rootdata = matis->sf_rootdata;
973   }
974   PetscFunctionReturn(0);
975 }
976 
977 /*@
978    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
979 
980    Collective on MPI_Comm
981 
982    Input Parameters:
983 +  B - the matrix
984 .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
985            (same value is used for all local rows)
986 .  d_nnz - array containing the number of nonzeros in the various rows of the
987            DIAGONAL portion of the local submatrix (possibly different for each row)
988            or NULL, if d_nz is used to specify the nonzero structure.
989            The size of this array is equal to the number of local rows, i.e 'm'.
990            For matrices that will be factored, you must leave room for (and set)
991            the diagonal entry even if it is zero.
992 .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
993            submatrix (same value is used for all local rows).
994 -  o_nnz - array containing the number of nonzeros in the various rows of the
995            OFF-DIAGONAL portion of the local submatrix (possibly different for
996            each row) or NULL, if o_nz is used to specify the nonzero
997            structure. The size of this array is equal to the number
998            of local rows, i.e 'm'.
999 
1000    If the *_nnz parameter is given then the *_nz parameter is ignored
1001 
1002    Level: intermediate
1003 
1004    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1005           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1006           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1007 
1008 .keywords: matrix
1009 
1010 .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1011 @*/
1012 PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
1013 {
1014   PetscErrorCode ierr;
1015 
1016   PetscFunctionBegin;
1017   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
1018   PetscValidType(B,1);
1019   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
1020   PetscFunctionReturn(0);
1021 }
1022 
1023 static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
1024 {
1025   Mat_IS         *matis = (Mat_IS*)(B->data);
1026   PetscInt       bs,i,nlocalcols;
1027   PetscErrorCode ierr;
1028 
1029   PetscFunctionBegin;
1030   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1031   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
1032 
1033   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
1034   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
1035 
1036   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
1037   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
1038 
1039   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1040   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
1041   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
1042   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1043 
1044   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
1045   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
1046 #if defined(PETSC_HAVE_HYPRE)
1047   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
1048 #endif
1049 
1050   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
1051   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
1052 
1053   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
1054   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
1055 
1056   /* for other matrix types */
1057   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
1058   PetscFunctionReturn(0);
1059 }
1060 
1061 PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
1062 {
1063   Mat_IS          *matis = (Mat_IS*)(A->data);
1064   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1065   const PetscInt  *global_indices_r,*global_indices_c;
1066   PetscInt        i,j,bs,rows,cols;
1067   PetscInt        lrows,lcols;
1068   PetscInt        local_rows,local_cols;
1069   PetscMPIInt     nsubdomains;
1070   PetscBool       isdense,issbaij;
1071   PetscErrorCode  ierr;
1072 
1073   PetscFunctionBegin;
1074   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
1075   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
1076   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
1077   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1078   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
1079   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1080   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1081   if (A->rmap->mapping != A->cmap->mapping) {
1082     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1083   } else {
1084     global_indices_c = global_indices_r;
1085   }
1086 
1087   if (issbaij) {
1088     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
1089   }
1090   /*
1091      An SF reduce is needed to sum up properly on shared rows.
1092      Note that generally preallocation is not exact, since it overestimates nonzeros
1093   */
1094   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
1095   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
1096   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
1097   /* All processes need to compute entire row ownership */
1098   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
1099   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1100   for (i=0;i<nsubdomains;i++) {
1101     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
1102       row_ownership[j] = i;
1103     }
1104   }
1105   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1106 
1107   /*
1108      my_dnz and my_onz contains exact contribution to preallocation from each local mat
1109      then, they will be summed up properly. This way, preallocation is always sufficient
1110   */
1111   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
1112   /* preallocation as a MATAIJ */
1113   if (isdense) { /* special case for dense local matrices */
1114     for (i=0;i<local_rows;i++) {
1115       PetscInt owner = row_ownership[global_indices_r[i]];
1116       for (j=0;j<local_cols;j++) {
1117         PetscInt index_col = global_indices_c[j];
1118         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1119           my_dnz[i] += 1;
1120         } else { /* offdiag block */
1121           my_onz[i] += 1;
1122         }
1123       }
1124     }
1125   } else if (matis->A->ops->getrowij) {
1126     const PetscInt *ii,*jj,*jptr;
1127     PetscBool      done;
1128     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1129     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1130     jptr = jj;
1131     for (i=0;i<local_rows;i++) {
1132       PetscInt index_row = global_indices_r[i];
1133       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1134         PetscInt owner = row_ownership[index_row];
1135         PetscInt index_col = global_indices_c[*jptr];
1136         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1137           my_dnz[i] += 1;
1138         } else { /* offdiag block */
1139           my_onz[i] += 1;
1140         }
1141         /* same as before, interchanging rows and cols */
1142         if (issbaij && index_col != index_row) {
1143           owner = row_ownership[index_col];
1144           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1145             my_dnz[*jptr] += 1;
1146           } else {
1147             my_onz[*jptr] += 1;
1148           }
1149         }
1150       }
1151     }
1152     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1153     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1154   } else { /* loop over rows and use MatGetRow */
1155     for (i=0;i<local_rows;i++) {
1156       const PetscInt *cols;
1157       PetscInt       ncols,index_row = global_indices_r[i];
1158       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
1159       for (j=0;j<ncols;j++) {
1160         PetscInt owner = row_ownership[index_row];
1161         PetscInt index_col = global_indices_c[cols[j]];
1162         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1163           my_dnz[i] += 1;
1164         } else { /* offdiag block */
1165           my_onz[i] += 1;
1166         }
1167         /* same as before, interchanging rows and cols */
1168         if (issbaij && index_col != index_row) {
1169           owner = row_ownership[index_col];
1170           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1171             my_dnz[cols[j]] += 1;
1172           } else {
1173             my_onz[cols[j]] += 1;
1174           }
1175         }
1176       }
1177       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
1178     }
1179   }
1180   if (global_indices_c != global_indices_r) {
1181     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1182   }
1183   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1184   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1185 
1186   /* Reduce my_dnz and my_onz */
1187   if (maxreduce) {
1188     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
1189     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1190     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
1191     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1192   } else {
1193     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
1194     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1195     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
1196     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1197   }
1198   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
1199 
1200   /* Resize preallocation if overestimated */
1201   for (i=0;i<lrows;i++) {
1202     dnz[i] = PetscMin(dnz[i],lcols);
1203     onz[i] = PetscMin(onz[i],cols-lcols);
1204   }
1205 
1206   /* Set preallocation */
1207   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
1208   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
1209   for (i=0;i<lrows/bs;i++) {
1210     dnz[i] = dnz[i*bs]/bs;
1211     onz[i] = onz[i*bs]/bs;
1212   }
1213   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
1214   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
1215   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
1216   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
1217   if (issbaij) {
1218     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
1219   }
1220   PetscFunctionReturn(0);
1221 }
1222 
1223 static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1224 {
1225   Mat_IS         *matis = (Mat_IS*)(mat->data);
1226   Mat            local_mat;
1227   /* info on mat */
1228   PetscInt       bs,rows,cols,lrows,lcols;
1229   PetscInt       local_rows,local_cols;
1230   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1231 #if defined (PETSC_USE_DEBUG)
1232   PetscBool      lb[4],bb[4];
1233 #endif
1234   PetscMPIInt    nsubdomains;
1235   /* values insertion */
1236   PetscScalar    *array;
1237   /* work */
1238   PetscErrorCode ierr;
1239 
1240   PetscFunctionBegin;
1241   /* get info from mat */
1242   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
1243   if (nsubdomains == 1) {
1244     Mat            B;
1245     IS             rows,cols;
1246     IS             irows,icols;
1247     const PetscInt *ridxs,*cidxs;
1248 
1249     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
1250     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1251     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
1252     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
1253     ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1254     ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1255     ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr);
1256     ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr);
1257     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
1258     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1259     ierr = ISDestroy(&cols);CHKERRQ(ierr);
1260     ierr = ISDestroy(&rows);CHKERRQ(ierr);
1261     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
1262     ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1263     ierr = MatDestroy(&B);CHKERRQ(ierr);
1264     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1265     ierr = ISDestroy(&irows);CHKERRQ(ierr);
1266     PetscFunctionReturn(0);
1267   }
1268   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1269   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1270   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1271   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1272   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
1273   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1274   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1275   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1276   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1277 #if defined (PETSC_USE_DEBUG)
1278   lb[0] = isseqdense;
1279   lb[1] = isseqaij;
1280   lb[2] = isseqbaij;
1281   lb[3] = isseqsbaij;
1282   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1283   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1284 #endif
1285 
1286   if (reuse == MAT_INITIAL_MATRIX) {
1287     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
1288     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
1289     if (!isseqsbaij) {
1290       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1291     } else {
1292       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1293     }
1294     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
1295     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1296   } else {
1297     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1298     /* some checks */
1299     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1300     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
1301     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
1302     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
1303     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
1304     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
1305     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
1306     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1307     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1308   }
1309 
1310   if (isseqsbaij) {
1311     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1312   } else {
1313     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1314     local_mat = matis->A;
1315   }
1316 
1317   /* Set values */
1318   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1319   if (isseqdense) { /* special case for dense local matrices */
1320     PetscInt i,*dummy;
1321 
1322     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
1323     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
1324     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1325     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
1326     ierr = MatSetValuesLocal(*M,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
1327     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
1328     ierr = PetscFree(dummy);CHKERRQ(ierr);
1329   } else if (isseqaij) {
1330     PetscInt  i,nvtxs,*xadj,*adjncy;
1331     PetscBool done;
1332 
1333     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1334     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1335     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1336     for (i=0;i<nvtxs;i++) {
1337       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1338     }
1339     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1340     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1341     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1342   } else { /* very basic values insertion for all other matrix types */
1343     PetscInt i;
1344 
1345     for (i=0;i<local_rows;i++) {
1346       PetscInt       j;
1347       const PetscInt *local_indices_cols;
1348 
1349       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1350       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1351       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1352     }
1353   }
1354   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1355   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1356   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1357   if (isseqdense) {
1358     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1359   }
1360   PetscFunctionReturn(0);
1361 }
1362 
1363 /*@
1364     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1365 
1366   Input Parameter:
1367 .  mat - the matrix (should be of type MATIS)
1368 .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1369 
1370   Output Parameter:
1371 .  newmat - the matrix in AIJ format
1372 
1373   Level: developer
1374 
1375   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1376 
1377 .seealso: MATIS
1378 @*/
1379 PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1380 {
1381   PetscErrorCode ierr;
1382 
1383   PetscFunctionBegin;
1384   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1385   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1386   PetscValidPointer(newmat,3);
1387   if (reuse != MAT_INITIAL_MATRIX) {
1388     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1389     PetscCheckSameComm(mat,1,*newmat,3);
1390     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1391   }
1392   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1393   PetscFunctionReturn(0);
1394 }
1395 
1396 PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1397 {
1398   PetscErrorCode ierr;
1399   Mat_IS         *matis = (Mat_IS*)(mat->data);
1400   PetscInt       bs,m,n,M,N;
1401   Mat            B,localmat;
1402 
1403   PetscFunctionBegin;
1404   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1405   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1406   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1407   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1408   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1409   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1410   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1411   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1412   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1413   *newmat = B;
1414   PetscFunctionReturn(0);
1415 }
1416 
1417 static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
1418 {
1419   PetscErrorCode ierr;
1420   Mat_IS         *matis = (Mat_IS*)A->data;
1421   PetscBool      local_sym;
1422 
1423   PetscFunctionBegin;
1424   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1425   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1426   PetscFunctionReturn(0);
1427 }
1428 
1429 static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
1430 {
1431   PetscErrorCode ierr;
1432   Mat_IS         *matis = (Mat_IS*)A->data;
1433   PetscBool      local_sym;
1434 
1435   PetscFunctionBegin;
1436   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1437   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1438   PetscFunctionReturn(0);
1439 }
1440 
1441 static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
1442 {
1443   PetscErrorCode ierr;
1444   Mat_IS         *matis = (Mat_IS*)A->data;
1445   PetscBool      local_sym;
1446 
1447   PetscFunctionBegin;
1448   if (A->rmap->mapping != A->cmap->mapping) {
1449     *flg = PETSC_FALSE;
1450     PetscFunctionReturn(0);
1451   }
1452   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
1453   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
1454   PetscFunctionReturn(0);
1455 }
1456 
1457 static PetscErrorCode MatDestroy_IS(Mat A)
1458 {
1459   PetscErrorCode ierr;
1460   Mat_IS         *b = (Mat_IS*)A->data;
1461 
1462   PetscFunctionBegin;
1463   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1464   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1465   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
1466   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
1467   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
1468   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1469   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1470   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1471   if (b->sf != b->csf) {
1472     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1473     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1474   }
1475   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
1476   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1477   ierr = PetscFree(A->data);CHKERRQ(ierr);
1478   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1479   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1480   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1481   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
1482   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1483   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1484   PetscFunctionReturn(0);
1485 }
1486 
1487 static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1488 {
1489   PetscErrorCode ierr;
1490   Mat_IS         *is  = (Mat_IS*)A->data;
1491   PetscScalar    zero = 0.0;
1492 
1493   PetscFunctionBegin;
1494   /*  scatter the global vector x into the local work vector */
1495   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1496   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1497 
1498   /* multiply the local matrix */
1499   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1500 
1501   /* scatter product back into global memory */
1502   ierr = VecSet(y,zero);CHKERRQ(ierr);
1503   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1504   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1505   PetscFunctionReturn(0);
1506 }
1507 
1508 static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
1509 {
1510   Vec            temp_vec;
1511   PetscErrorCode ierr;
1512 
1513   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1514   if (v3 != v2) {
1515     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1516     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1517   } else {
1518     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1519     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1520     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1521     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1522     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1523   }
1524   PetscFunctionReturn(0);
1525 }
1526 
1527 static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
1528 {
1529   Mat_IS         *is = (Mat_IS*)A->data;
1530   PetscErrorCode ierr;
1531 
1532   PetscFunctionBegin;
1533   /*  scatter the global vector x into the local work vector */
1534   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1535   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1536 
1537   /* multiply the local matrix */
1538   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
1539 
1540   /* scatter product back into global vector */
1541   ierr = VecSet(x,0);CHKERRQ(ierr);
1542   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1543   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1544   PetscFunctionReturn(0);
1545 }
1546 
1547 static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
1548 {
1549   Vec            temp_vec;
1550   PetscErrorCode ierr;
1551 
1552   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1553   if (v3 != v2) {
1554     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1555     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1556   } else {
1557     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1558     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1559     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1560     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1561     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1562   }
1563   PetscFunctionReturn(0);
1564 }
1565 
1566 static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1567 {
1568   Mat_IS         *a = (Mat_IS*)A->data;
1569   PetscErrorCode ierr;
1570   PetscViewer    sviewer;
1571   PetscBool      isascii,view = PETSC_TRUE;
1572 
1573   PetscFunctionBegin;
1574   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1575   if (isascii)  {
1576     PetscViewerFormat format;
1577 
1578     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1579     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1580   }
1581   if (!view) PetscFunctionReturn(0);
1582   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1583   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
1584   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1585   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1586   PetscFunctionReturn(0);
1587 }
1588 
1589 static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1590 {
1591   PetscErrorCode ierr;
1592   PetscInt       nr,rbs,nc,cbs;
1593   Mat_IS         *is = (Mat_IS*)A->data;
1594   IS             from,to;
1595   Vec            cglobal,rglobal;
1596 
1597   PetscFunctionBegin;
1598   PetscCheckSameComm(A,1,rmapping,2);
1599   PetscCheckSameComm(A,1,cmapping,3);
1600   /* Destroy any previous data */
1601   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
1602   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
1603   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1604   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1605   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
1606   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
1607   if (is->csf != is->sf) {
1608     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
1609     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
1610   }
1611   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
1612   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
1613 
1614   /* Setup Layout and set local to global maps */
1615   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1616   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1617   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1618   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1619 
1620   /* Create the local matrix A */
1621   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1622   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1623   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1624   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1625   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1626   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1627   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1628   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1629   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1630   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1631   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1632   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
1633   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
1634 
1635   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1636     /* Create the local work vectors */
1637     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1638 
1639     /* setup the global to local scatters */
1640     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1641     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1642     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1643     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1644     if (rmapping != cmapping) {
1645       ierr = ISDestroy(&to);CHKERRQ(ierr);
1646       ierr = ISDestroy(&from);CHKERRQ(ierr);
1647       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1648       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1649       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1650     } else {
1651       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1652       is->cctx = is->rctx;
1653     }
1654 
1655     /* interface counter vector (local) */
1656     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
1657     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
1658     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1659     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1660     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1661     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1662 
1663     /* free workspace */
1664     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1665     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
1666     ierr = ISDestroy(&to);CHKERRQ(ierr);
1667     ierr = ISDestroy(&from);CHKERRQ(ierr);
1668   }
1669   ierr = MatSetUp(A);CHKERRQ(ierr);
1670   PetscFunctionReturn(0);
1671 }
1672 
1673 static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
1674 {
1675   Mat_IS         *is = (Mat_IS*)mat->data;
1676   PetscErrorCode ierr;
1677 #if defined(PETSC_USE_DEBUG)
1678   PetscInt       i,zm,zn;
1679 #endif
1680   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1681 
1682   PetscFunctionBegin;
1683 #if defined(PETSC_USE_DEBUG)
1684   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);
1685   /* count negative indices */
1686   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
1687   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
1688 #endif
1689   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
1690   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
1691 #if defined(PETSC_USE_DEBUG)
1692   /* count negative indices (should be the same as before) */
1693   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
1694   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
1695   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");
1696   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");
1697 #endif
1698   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1699   PetscFunctionReturn(0);
1700 }
1701 
1702 static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
1703 {
1704   Mat_IS         *is = (Mat_IS*)mat->data;
1705   PetscErrorCode ierr;
1706 #if defined(PETSC_USE_DEBUG)
1707   PetscInt       i,zm,zn;
1708 #endif
1709   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1710 
1711   PetscFunctionBegin;
1712 #if defined(PETSC_USE_DEBUG)
1713   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);
1714   /* count negative indices */
1715   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
1716   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
1717 #endif
1718   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
1719   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
1720 #if defined(PETSC_USE_DEBUG)
1721   /* count negative indices (should be the same as before) */
1722   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
1723   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
1724   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");
1725   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");
1726 #endif
1727   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1728   PetscFunctionReturn(0);
1729 }
1730 
1731 static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1732 {
1733   PetscErrorCode ierr;
1734   Mat_IS         *is = (Mat_IS*)A->data;
1735 
1736   PetscFunctionBegin;
1737   if (is->A->rmap->mapping) {
1738     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1739   } else {
1740     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1741   }
1742   PetscFunctionReturn(0);
1743 }
1744 
1745 static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1746 {
1747   PetscErrorCode ierr;
1748   Mat_IS         *is = (Mat_IS*)A->data;
1749 
1750   PetscFunctionBegin;
1751   if (is->A->rmap->mapping) {
1752 #if defined(PETSC_USE_DEBUG)
1753     PetscInt ibs,bs;
1754 
1755     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
1756     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
1757     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
1758 #endif
1759     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1760   } else {
1761     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1762   }
1763   PetscFunctionReturn(0);
1764 }
1765 
1766 static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1767 {
1768   Mat_IS         *is = (Mat_IS*)A->data;
1769   PetscErrorCode ierr;
1770 
1771   PetscFunctionBegin;
1772   if (!n) {
1773     is->pure_neumann = PETSC_TRUE;
1774   } else {
1775     PetscInt i;
1776     is->pure_neumann = PETSC_FALSE;
1777 
1778     if (columns) {
1779       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1780     } else {
1781       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1782     }
1783     if (diag != 0.) {
1784       const PetscScalar *array;
1785       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1786       for (i=0; i<n; i++) {
1787         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1788       }
1789       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1790     }
1791     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1792     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1793   }
1794   PetscFunctionReturn(0);
1795 }
1796 
1797 static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
1798 {
1799   Mat_IS         *matis = (Mat_IS*)A->data;
1800   PetscInt       nr,nl,len,i;
1801   PetscInt       *lrows;
1802   PetscErrorCode ierr;
1803 
1804   PetscFunctionBegin;
1805 #if defined(PETSC_USE_DEBUG)
1806   if (columns || diag != 0. || (x && b)) {
1807     PetscBool cong;
1808 
1809     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1810     cong = (PetscBool)(cong && matis->sf == matis->csf);
1811     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");
1812     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");
1813     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");
1814   }
1815 #endif
1816   /* get locally owned rows */
1817   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
1818   /* fix right hand side if needed */
1819   if (x && b) {
1820     const PetscScalar *xx;
1821     PetscScalar       *bb;
1822 
1823     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
1824     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
1825     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
1826     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
1827     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
1828   }
1829   /* get rows associated to the local matrices */
1830   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
1831   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
1832   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
1833   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
1834   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
1835   ierr = PetscFree(lrows);CHKERRQ(ierr);
1836   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1837   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1838   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
1839   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1840   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
1841   ierr = PetscFree(lrows);CHKERRQ(ierr);
1842   PetscFunctionReturn(0);
1843 }
1844 
1845 static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1846 {
1847   PetscErrorCode ierr;
1848 
1849   PetscFunctionBegin;
1850   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1851   PetscFunctionReturn(0);
1852 }
1853 
1854 static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1855 {
1856   PetscErrorCode ierr;
1857 
1858   PetscFunctionBegin;
1859   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1860   PetscFunctionReturn(0);
1861 }
1862 
1863 static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1864 {
1865   Mat_IS         *is = (Mat_IS*)A->data;
1866   PetscErrorCode ierr;
1867 
1868   PetscFunctionBegin;
1869   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1870   PetscFunctionReturn(0);
1871 }
1872 
1873 static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1874 {
1875   Mat_IS         *is = (Mat_IS*)A->data;
1876   PetscErrorCode ierr;
1877 
1878   PetscFunctionBegin;
1879   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1880   /* fix for local empty rows/cols */
1881   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
1882     Mat                    newlA;
1883     ISLocalToGlobalMapping l2g;
1884     IS                     tis;
1885     const PetscScalar      *v;
1886     PetscInt               i,n,cf,*loce,*locf;
1887     PetscBool              sym;
1888 
1889     ierr = MatGetRowMaxAbs(is->A,is->y,NULL);CHKERRQ(ierr);
1890     ierr = MatIsSymmetric(is->A,PETSC_SMALL,&sym);CHKERRQ(ierr);
1891     if (!sym) SETERRQ(PetscObjectComm((PetscObject)is->A),PETSC_ERR_SUP,"Not yet implemented for unsymmetric case");
1892     ierr = VecGetLocalSize(is->y,&n);CHKERRQ(ierr);
1893     ierr = PetscMalloc1(n,&loce);CHKERRQ(ierr);
1894     ierr = PetscMalloc1(n,&locf);CHKERRQ(ierr);
1895     ierr = VecGetArrayRead(is->y,&v);CHKERRQ(ierr);
1896     for (i=0,cf=0;i<n;i++) {
1897       if (v[i] == 0.0) {
1898         loce[i] = -1;
1899       } else {
1900         loce[i]    = cf;
1901         locf[cf++] = i;
1902       }
1903     }
1904     ierr = VecRestoreArrayRead(is->y,&v);CHKERRQ(ierr);
1905     /* extract valid submatrix */
1906     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A),cf,locf,PETSC_USE_POINTER,&tis);CHKERRQ(ierr);
1907     ierr = MatCreateSubMatrix(is->A,tis,tis,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
1908     ierr = ISDestroy(&tis);CHKERRQ(ierr);
1909     /* attach local l2g map for successive calls of MatSetValues */
1910     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is->A),1,n,loce,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
1911     ierr = MatSetLocalToGlobalMapping(newlA,l2g,l2g);CHKERRQ(ierr);
1912     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
1913     /* attach new global l2g map */
1914     ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,cf,locf,locf);CHKERRQ(ierr);
1915     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,cf,locf,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
1916     ierr = MatSetLocalToGlobalMapping(A,l2g,l2g);CHKERRQ(ierr);
1917     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
1918     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
1919     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
1920   }
1921   is->locempty = PETSC_FALSE;
1922   PetscFunctionReturn(0);
1923 }
1924 
1925 static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1926 {
1927   Mat_IS *is = (Mat_IS*)mat->data;
1928 
1929   PetscFunctionBegin;
1930   *local = is->A;
1931   PetscFunctionReturn(0);
1932 }
1933 
1934 static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
1935 {
1936   PetscFunctionBegin;
1937   *local = NULL;
1938   PetscFunctionReturn(0);
1939 }
1940 
1941 /*@
1942     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1943 
1944   Input Parameter:
1945 .  mat - the matrix
1946 
1947   Output Parameter:
1948 .  local - the local matrix
1949 
1950   Level: advanced
1951 
1952   Notes:
1953     This can be called if you have precomputed the nonzero structure of the
1954   matrix and want to provide it to the inner matrix object to improve the performance
1955   of the MatSetValues() operation.
1956 
1957   Call MatISRestoreLocalMat() when finished with the local matrix.
1958 
1959 .seealso: MATIS
1960 @*/
1961 PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1962 {
1963   PetscErrorCode ierr;
1964 
1965   PetscFunctionBegin;
1966   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1967   PetscValidPointer(local,2);
1968   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1969   PetscFunctionReturn(0);
1970 }
1971 
1972 /*@
1973     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
1974 
1975   Input Parameter:
1976 .  mat - the matrix
1977 
1978   Output Parameter:
1979 .  local - the local matrix
1980 
1981   Level: advanced
1982 
1983 .seealso: MATIS
1984 @*/
1985 PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
1986 {
1987   PetscErrorCode ierr;
1988 
1989   PetscFunctionBegin;
1990   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1991   PetscValidPointer(local,2);
1992   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1993   PetscFunctionReturn(0);
1994 }
1995 
1996 static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
1997 {
1998   Mat_IS         *is = (Mat_IS*)mat->data;
1999   PetscInt       nrows,ncols,orows,ocols;
2000   PetscErrorCode ierr;
2001 
2002   PetscFunctionBegin;
2003   if (is->A) {
2004     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
2005     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2006     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);
2007   }
2008   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
2009   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
2010   is->A = local;
2011   PetscFunctionReturn(0);
2012 }
2013 
2014 /*@
2015     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
2016 
2017   Input Parameter:
2018 .  mat - the matrix
2019 .  local - the local matrix
2020 
2021   Output Parameter:
2022 
2023   Level: advanced
2024 
2025   Notes:
2026     This can be called if you have precomputed the local matrix and
2027   want to provide it to the matrix object MATIS.
2028 
2029 .seealso: MATIS
2030 @*/
2031 PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
2032 {
2033   PetscErrorCode ierr;
2034 
2035   PetscFunctionBegin;
2036   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2037   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
2038   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
2039   PetscFunctionReturn(0);
2040 }
2041 
2042 static PetscErrorCode MatZeroEntries_IS(Mat A)
2043 {
2044   Mat_IS         *a = (Mat_IS*)A->data;
2045   PetscErrorCode ierr;
2046 
2047   PetscFunctionBegin;
2048   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
2049   PetscFunctionReturn(0);
2050 }
2051 
2052 static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
2053 {
2054   Mat_IS         *is = (Mat_IS*)A->data;
2055   PetscErrorCode ierr;
2056 
2057   PetscFunctionBegin;
2058   ierr = MatScale(is->A,a);CHKERRQ(ierr);
2059   PetscFunctionReturn(0);
2060 }
2061 
2062 static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
2063 {
2064   Mat_IS         *is = (Mat_IS*)A->data;
2065   PetscErrorCode ierr;
2066 
2067   PetscFunctionBegin;
2068   /* get diagonal of the local matrix */
2069   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
2070 
2071   /* scatter diagonal back into global vector */
2072   ierr = VecSet(v,0);CHKERRQ(ierr);
2073   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2074   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2075   PetscFunctionReturn(0);
2076 }
2077 
2078 static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
2079 {
2080   Mat_IS         *a = (Mat_IS*)A->data;
2081   PetscErrorCode ierr;
2082 
2083   PetscFunctionBegin;
2084   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
2085   PetscFunctionReturn(0);
2086 }
2087 
2088 static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
2089 {
2090   Mat_IS         *y = (Mat_IS*)Y->data;
2091   Mat_IS         *x;
2092 #if defined(PETSC_USE_DEBUG)
2093   PetscBool      ismatis;
2094 #endif
2095   PetscErrorCode ierr;
2096 
2097   PetscFunctionBegin;
2098 #if defined(PETSC_USE_DEBUG)
2099   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
2100   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
2101 #endif
2102   x = (Mat_IS*)X->data;
2103   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
2104   PetscFunctionReturn(0);
2105 }
2106 
2107 static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
2108 {
2109   Mat                    lA;
2110   Mat_IS                 *matis;
2111   ISLocalToGlobalMapping rl2g,cl2g;
2112   IS                     is;
2113   const PetscInt         *rg,*rl;
2114   PetscInt               nrg;
2115   PetscInt               N,M,nrl,i,*idxs;
2116   PetscErrorCode         ierr;
2117 
2118   PetscFunctionBegin;
2119   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2120   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
2121   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
2122   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
2123 #if defined(PETSC_USE_DEBUG)
2124   for (i=0;i<nrl;i++) if (rl[i]>=nrg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row index %D -> %D greater than maximum possible %D",i,rl[i],nrg);
2125 #endif
2126   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
2127   /* map from [0,nrl) to row */
2128   for (i=0;i<nrl;i++) idxs[i] = rl[i];
2129 #if defined(PETSC_USE_DEBUG)
2130   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
2131 #else
2132   for (i=nrl;i<nrg;i++) idxs[i] = -1;
2133 #endif
2134   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
2135   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2136   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2137   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2138   ierr = ISDestroy(&is);CHKERRQ(ierr);
2139   /* compute new l2g map for columns */
2140   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2141     const PetscInt *cg,*cl;
2142     PetscInt       ncg;
2143     PetscInt       ncl;
2144 
2145     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2146     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2147     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2148     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2149 #if defined(PETSC_USE_DEBUG)
2150     for (i=0;i<ncl;i++) if (cl[i]>=ncg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local column index %D -> %D greater than maximum possible %D",i,cl[i],ncg);
2151 #endif
2152     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2153     /* map from [0,ncl) to col */
2154     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2155 #if defined(PETSC_USE_DEBUG)
2156     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2157 #else
2158     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2159 #endif
2160     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2161     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2162     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2163     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2164     ierr = ISDestroy(&is);CHKERRQ(ierr);
2165   } else {
2166     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2167     cl2g = rl2g;
2168   }
2169   /* create the MATIS submatrix */
2170   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2171   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2172   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2173   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2174   matis = (Mat_IS*)((*submat)->data);
2175   matis->islocalref = PETSC_TRUE;
2176   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2177   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2178   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2179   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2180   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2181   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2182   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2183   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2184   /* remove unsupported ops */
2185   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2186   (*submat)->ops->destroy               = MatDestroy_IS;
2187   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2188   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2189   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2190   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2191   PetscFunctionReturn(0);
2192 }
2193 
2194 static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
2195 {
2196   Mat_IS         *a = (Mat_IS*)A->data;
2197   PetscErrorCode ierr;
2198 
2199   PetscFunctionBegin;
2200   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
2201   ierr = PetscObjectOptionsBegin((PetscObject)A);
2202   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns",NULL,a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
2203   ierr = PetscOptionsEnd();CHKERRQ(ierr);
2204   PetscFunctionReturn(0);
2205 }
2206 
2207 /*@
2208     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2209        process but not across processes.
2210 
2211    Input Parameters:
2212 +     comm    - MPI communicator that will share the matrix
2213 .     bs      - block size of the matrix
2214 .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2215 .     rmap    - local to global map for rows
2216 -     cmap    - local to global map for cols
2217 
2218    Output Parameter:
2219 .    A - the resulting matrix
2220 
2221    Level: advanced
2222 
2223    Notes: See MATIS for more details.
2224           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
2225           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
2226           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2227 
2228 .seealso: MATIS, MatSetLocalToGlobalMapping()
2229 @*/
2230 PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2231 {
2232   PetscErrorCode ierr;
2233 
2234   PetscFunctionBegin;
2235   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2236   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2237   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
2238   if (bs > 0) {
2239     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
2240   }
2241   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2242   if (rmap && cmap) {
2243     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2244   } else if (!rmap) {
2245     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2246   } else {
2247     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2248   }
2249   PetscFunctionReturn(0);
2250 }
2251 
2252 /*MC
2253    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2254    This stores the matrices in globally unassembled form. Each processor
2255    assembles only its local Neumann problem and the parallel matrix vector
2256    product is handled "implicitly".
2257 
2258    Operations Provided:
2259 +  MatMult()
2260 .  MatMultAdd()
2261 .  MatMultTranspose()
2262 .  MatMultTransposeAdd()
2263 .  MatZeroEntries()
2264 .  MatSetOption()
2265 .  MatZeroRows()
2266 .  MatSetValues()
2267 .  MatSetValuesBlocked()
2268 .  MatSetValuesLocal()
2269 .  MatSetValuesBlockedLocal()
2270 .  MatScale()
2271 .  MatGetDiagonal()
2272 .  MatMissingDiagonal()
2273 .  MatDuplicate()
2274 .  MatCopy()
2275 .  MatAXPY()
2276 .  MatCreateSubMatrix()
2277 .  MatGetLocalSubMatrix()
2278 .  MatTranspose()
2279 -  MatSetLocalToGlobalMapping()
2280 
2281    Options Database Keys:
2282 . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2283 
2284    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
2285 
2286           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2287 
2288           You can do matrix preallocation on the local matrix after you obtain it with
2289           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2290 
2291   Level: advanced
2292 
2293 .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2294 
2295 M*/
2296 
2297 PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2298 {
2299   PetscErrorCode ierr;
2300   Mat_IS         *b;
2301 
2302   PetscFunctionBegin;
2303   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2304   A->data = (void*)b;
2305 
2306   /* matrix ops */
2307   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2308   A->ops->mult                    = MatMult_IS;
2309   A->ops->multadd                 = MatMultAdd_IS;
2310   A->ops->multtranspose           = MatMultTranspose_IS;
2311   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2312   A->ops->destroy                 = MatDestroy_IS;
2313   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
2314   A->ops->setvalues               = MatSetValues_IS;
2315   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2316   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2317   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
2318   A->ops->zerorows                = MatZeroRows_IS;
2319   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2320   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2321   A->ops->assemblyend             = MatAssemblyEnd_IS;
2322   A->ops->view                    = MatView_IS;
2323   A->ops->zeroentries             = MatZeroEntries_IS;
2324   A->ops->scale                   = MatScale_IS;
2325   A->ops->getdiagonal             = MatGetDiagonal_IS;
2326   A->ops->setoption               = MatSetOption_IS;
2327   A->ops->ishermitian             = MatIsHermitian_IS;
2328   A->ops->issymmetric             = MatIsSymmetric_IS;
2329   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2330   A->ops->duplicate               = MatDuplicate_IS;
2331   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
2332   A->ops->copy                    = MatCopy_IS;
2333   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
2334   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
2335   A->ops->axpy                    = MatAXPY_IS;
2336   A->ops->diagonalset             = MatDiagonalSet_IS;
2337   A->ops->shift                   = MatShift_IS;
2338   A->ops->transpose               = MatTranspose_IS;
2339   A->ops->getinfo                 = MatGetInfo_IS;
2340   A->ops->diagonalscale           = MatDiagonalScale_IS;
2341   A->ops->setfromoptions          = MatSetFromOptions_IS;
2342 
2343   /* special MATIS functions */
2344   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
2345   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
2346   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2347   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
2348   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2349   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
2350   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2351   PetscFunctionReturn(0);
2352 }
2353