xref: /petsc/src/mat/impls/is/matis.c (revision b0aa34280e6fae6ba07369f3f988f126a25945fc)
1be1d678aSKris Buschelman 
2b4319ba4SBarry Smith /*
3b4319ba4SBarry Smith     Creates a matrix class for using the Neumann-Neumann type preconditioners.
4b4319ba4SBarry Smith     This stores the matrices in globally unassembled form. Each processor
5b4319ba4SBarry Smith     assembles only its local Neumann problem and the parallel matrix vector
6b4319ba4SBarry Smith     product is handled "implicitly".
7b4319ba4SBarry Smith 
8b4319ba4SBarry Smith     Currently this allows for only one subdomain per processor.
9b4319ba4SBarry Smith */
10b4319ba4SBarry Smith 
11c6db04a5SJed Brown #include <../src/mat/impls/is/matis.h>      /*I "petscmat.h" I*/
1228f4e0baSStefano Zampini 
13f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
14f26d0771SStefano Zampini 
15a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat);
167230de76SStefano Zampini static PetscErrorCode MatISZeroRowsLocal_Private(Mat,PetscInt,const PetscInt[],PetscScalar);
17a72627d2SStefano Zampini 
1828f4e0baSStefano Zampini #undef __FUNCT__
19f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS"
20f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
21f26d0771SStefano Zampini {
22f26d0771SStefano Zampini   PetscErrorCode ierr;
23f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
24f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
25f26d0771SStefano Zampini 
26f26d0771SStefano Zampini   PetscFunctionBegin;
27f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
28f26d0771SStefano Zampini   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);
29f26d0771SStefano Zampini #endif
30f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
31f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
32f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
33f26d0771SStefano Zampini   PetscFunctionReturn(0);
34f26d0771SStefano Zampini }
35f26d0771SStefano Zampini 
36f26d0771SStefano Zampini #undef __FUNCT__
37f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS"
38f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
39f26d0771SStefano Zampini {
40f26d0771SStefano Zampini   PetscErrorCode ierr;
41f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
42f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
43f26d0771SStefano Zampini 
44f26d0771SStefano Zampini   PetscFunctionBegin;
45f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
46f26d0771SStefano Zampini   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);
47f26d0771SStefano Zampini #endif
48f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
49f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
50f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
51f26d0771SStefano Zampini   PetscFunctionReturn(0);
52f26d0771SStefano Zampini }
53f26d0771SStefano Zampini 
54f26d0771SStefano Zampini #undef __FUNCT__
55a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private"
56a8116848SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[],const PetscInt gidxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
57a8116848SStefano Zampini {
58a8116848SStefano Zampini   PetscInt      *owners = map->range;
59a8116848SStefano Zampini   PetscInt       n      = map->n;
60a8116848SStefano Zampini   PetscSF        sf;
61a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
62a8116848SStefano Zampini   PetscSFNode   *ridxs;
63a8116848SStefano Zampini   PetscMPIInt    rank;
64a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
65a8116848SStefano Zampini   PetscErrorCode ierr;
66a8116848SStefano Zampini 
67a8116848SStefano Zampini   PetscFunctionBegin;
68a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
69a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
70a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
71a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
72a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
73a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
74a8116848SStefano Zampini     const PetscInt idx = idxs[r];
75a8116848SStefano Zampini     if (idx < 0 || map->N <= idx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index %D out of range [0,%D)",idx,map->N);
76a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
77a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
78a8116848SStefano Zampini     }
79a8116848SStefano Zampini     ridxs[r].rank = p;
80a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
81a8116848SStefano Zampini   }
82a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
83a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
84a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
85a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
86a8116848SStefano Zampini   if ((gidxs && ogidxs) || ogidxs) {
87a8116848SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
88a8116848SStefano Zampini     if (!gidxs) { /* if gidxs is not provided, global indices are inferred */
89a8116848SStefano Zampini       PetscInt cum = 0,start,*work2;
90a8116848SStefano Zampini       ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
91a8116848SStefano Zampini       for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
92a8116848SStefano Zampini       ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
93a8116848SStefano Zampini       start -= cum;
94a8116848SStefano Zampini       cum = 0;
95a8116848SStefano Zampini       for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
96a8116848SStefano Zampini       ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
97a8116848SStefano Zampini       ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
98a8116848SStefano Zampini       ierr = PetscFree(work2);CHKERRQ(ierr);
99a8116848SStefano Zampini     } else {
100a8116848SStefano Zampini       ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)gidxs,work,MPIU_REPLACE);CHKERRQ(ierr);
101a8116848SStefano Zampini       ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)gidxs,work,MPIU_REPLACE);CHKERRQ(ierr);
102a8116848SStefano Zampini     }
103a8116848SStefano Zampini   }
104a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
105a8116848SStefano Zampini   /* Compress and put in indices */
106a8116848SStefano Zampini   for (r = 0; r < n; ++r)
107a8116848SStefano Zampini     if (lidxs[r] >= 0) {
108a8116848SStefano Zampini       if (work) work[len] = work[r];
109a8116848SStefano Zampini       lidxs[len++] = r;
110a8116848SStefano Zampini     }
111a8116848SStefano Zampini   if (on) *on = len;
112a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
113a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
114a8116848SStefano Zampini   PetscFunctionReturn(0);
115a8116848SStefano Zampini }
116a8116848SStefano Zampini 
117a8116848SStefano Zampini #undef __FUNCT__
118a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS"
119a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
120a8116848SStefano Zampini {
121a8116848SStefano Zampini   Mat               locmat,newlocmat;
122a8116848SStefano Zampini   Mat_IS            *newmatis;
123a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
124a8116848SStefano Zampini   Vec               rtest,ltest;
125a8116848SStefano Zampini   const PetscScalar *array;
126a8116848SStefano Zampini #endif
127a8116848SStefano Zampini   const PetscInt    *idxs;
128a8116848SStefano Zampini   PetscInt          i,m,n;
129a8116848SStefano Zampini   PetscErrorCode    ierr;
130a8116848SStefano Zampini 
131a8116848SStefano Zampini   PetscFunctionBegin;
132a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
133a8116848SStefano Zampini     PetscBool ismatis;
134a8116848SStefano Zampini 
135a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
136a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
137a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
138a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
139a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
140a8116848SStefano Zampini   }
141a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
142a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
143a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
144a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
145a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
146a8116848SStefano Zampini   for (i=0;i<n;i++) {
147a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
148a8116848SStefano Zampini   }
149a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
150a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
151a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
152a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
153a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
154fd479f66SMatthew G. Knepley   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]));
155a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
156a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
157a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
158a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
159a8116848SStefano Zampini   for (i=0;i<n;i++) {
160a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
161a8116848SStefano Zampini   }
162a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
163a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
164a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
165a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
166a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
167fd479f66SMatthew G. Knepley   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]));
168a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
169a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
170a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
171a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
172a8116848SStefano Zampini #endif
173a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
174a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
175a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
176a8116848SStefano Zampini     IS                     is;
177a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1786dd40735SStefano Zampini     PetscInt               ll,newloc;
179a8116848SStefano Zampini     MPI_Comm               comm;
180a8116848SStefano Zampini 
181a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
182a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
183a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
184a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
185a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
186a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
187a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
188a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
189a8116848SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,NULL,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
190a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
191a8116848SStefano Zampini     if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
192a8116848SStefano Zampini       ierr = MatISComputeSF_Private(mat);CHKERRQ(ierr);
193a8116848SStefano Zampini     }
194a8116848SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
195a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
196a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
197a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
198a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
199a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
200a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
201a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
202a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
203a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++)
204a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
205a8116848SStefano Zampini         lidxs[newloc] = i;
206a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
207a8116848SStefano Zampini       }
208a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
209a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
210a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
211a8116848SStefano Zampini     /* local is to extract local submatrix */
212a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
213a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
214a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
215a8116848SStefano Zampini       PetscBool cong;
216a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
217a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
218a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
219a8116848SStefano Zampini     }
220a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
221a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
222a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
223a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
224a8116848SStefano Zampini     } else {
225a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
226a8116848SStefano Zampini 
227a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
228a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
229a8116848SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,NULL,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
230a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
231a8116848SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
232a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
233a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
234a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
235a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
236a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
237a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
238a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
239a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
240a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++)
241a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
242a8116848SStefano Zampini           lidxs[newloc] = i;
243a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
244a8116848SStefano Zampini         }
245a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
246a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
247a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
248a8116848SStefano Zampini       /* local is to extract local submatrix */
249a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
250a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
251a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
252a8116848SStefano Zampini     }
253a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
254a8116848SStefano Zampini   } else {
255a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
256a8116848SStefano Zampini   }
257a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
258a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
259a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
260a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
261a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
262a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
263a8116848SStefano Zampini   }
264a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
265a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
266a8116848SStefano Zampini   PetscFunctionReturn(0);
267a8116848SStefano Zampini }
268a8116848SStefano Zampini 
269a8116848SStefano Zampini #undef __FUNCT__
2702b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS"
271a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
2722b404112SStefano Zampini {
2732b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
2742b404112SStefano Zampini   PetscBool      ismatis;
2752b404112SStefano Zampini   PetscErrorCode ierr;
2762b404112SStefano Zampini 
2772b404112SStefano Zampini   PetscFunctionBegin;
2782b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
2792b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
2802b404112SStefano Zampini   b = (Mat_IS*)B->data;
2812b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
2822b404112SStefano Zampini   PetscFunctionReturn(0);
2832b404112SStefano Zampini }
2842b404112SStefano Zampini 
2852b404112SStefano Zampini #undef __FUNCT__
2866bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS"
287a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
2886bd84002SStefano Zampini {
289527b2640SStefano Zampini   Vec               v;
290527b2640SStefano Zampini   const PetscScalar *array;
291527b2640SStefano Zampini   PetscInt          i,n;
2926bd84002SStefano Zampini   PetscErrorCode    ierr;
2936bd84002SStefano Zampini 
2946bd84002SStefano Zampini   PetscFunctionBegin;
295527b2640SStefano Zampini   *missing = PETSC_FALSE;
296527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
297527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
298527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
299527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
300527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
301527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
302527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
303527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
304527b2640SStefano Zampini   if (d) {
305527b2640SStefano Zampini     *d = -1;
306527b2640SStefano Zampini     if (*missing) {
307527b2640SStefano Zampini       PetscInt rstart;
308527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
309527b2640SStefano Zampini       *d = i+rstart;
310527b2640SStefano Zampini     }
311527b2640SStefano Zampini   }
3126bd84002SStefano Zampini   PetscFunctionReturn(0);
3136bd84002SStefano Zampini }
3146bd84002SStefano Zampini 
3156bd84002SStefano Zampini #undef __FUNCT__
31628f4e0baSStefano Zampini #define __FUNCT__ "MatISComputeSF_Private"
317a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat B)
31828f4e0baSStefano Zampini {
31928f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
32028f4e0baSStefano Zampini   const PetscInt *gidxs;
32128f4e0baSStefano Zampini   PetscErrorCode ierr;
32228f4e0baSStefano Zampini 
32328f4e0baSStefano Zampini   PetscFunctionBegin;
32428f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,&matis->sf_nleaves,NULL);CHKERRQ(ierr);
32528f4e0baSStefano Zampini   ierr = MatGetLocalSize(B,&matis->sf_nroots,NULL);CHKERRQ(ierr);
32628f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
3273bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
32828f4e0baSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,matis->sf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
3293bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
33028f4e0baSStefano Zampini   ierr = PetscMalloc2(matis->sf_nroots,&matis->sf_rootdata,matis->sf_nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
331a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
332a8116848SStefano Zampini     ierr = MatGetSize(matis->A,NULL,&matis->csf_nleaves);CHKERRQ(ierr);
333a8116848SStefano Zampini     ierr = MatGetLocalSize(B,NULL,&matis->csf_nroots);CHKERRQ(ierr);
334a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
335a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
336a8116848SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,matis->csf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
337a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
338a8116848SStefano Zampini     ierr = PetscMalloc2(matis->csf_nroots,&matis->csf_rootdata,matis->csf_nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
339a8116848SStefano Zampini   } else {
340a8116848SStefano Zampini     matis->csf = matis->sf;
341a8116848SStefano Zampini     matis->csf_nleaves = matis->sf_nleaves;
342a8116848SStefano Zampini     matis->csf_nroots = matis->sf_nroots;
343a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
344a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
345a8116848SStefano Zampini   }
34628f4e0baSStefano Zampini   PetscFunctionReturn(0);
34728f4e0baSStefano Zampini }
3482e1947a5SStefano Zampini 
3492e1947a5SStefano Zampini #undef __FUNCT__
3502e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
351eb82efa4SStefano Zampini /*@
352a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
353a88811baSStefano Zampini 
354a88811baSStefano Zampini    Collective on MPI_Comm
355a88811baSStefano Zampini 
356a88811baSStefano Zampini    Input Parameters:
357a88811baSStefano Zampini +  B - the matrix
358a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
359a88811baSStefano Zampini            (same value is used for all local rows)
360a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
361a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
362a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
363a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
364a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
365a88811baSStefano Zampini            the diagonal entry even if it is zero.
366a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
367a88811baSStefano Zampini            submatrix (same value is used for all local rows).
368a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
369a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
370a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
371a88811baSStefano Zampini            structure. The size of this array is equal to the number
372a88811baSStefano Zampini            of local rows, i.e 'm'.
373a88811baSStefano Zampini 
374a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
375a88811baSStefano Zampini 
376a88811baSStefano Zampini    Level: intermediate
377a88811baSStefano Zampini 
378a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
379a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
380a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
381a88811baSStefano Zampini 
382a88811baSStefano Zampini .keywords: matrix
383a88811baSStefano Zampini 
3843c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
385a88811baSStefano Zampini @*/
3862e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
3872e1947a5SStefano Zampini {
3882e1947a5SStefano Zampini   PetscErrorCode ierr;
3892e1947a5SStefano Zampini 
3902e1947a5SStefano Zampini   PetscFunctionBegin;
3912e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
3922e1947a5SStefano Zampini   PetscValidType(B,1);
3932e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
3942e1947a5SStefano Zampini   PetscFunctionReturn(0);
3952e1947a5SStefano Zampini }
3962e1947a5SStefano Zampini 
3972e1947a5SStefano Zampini #undef __FUNCT__
3982e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
3997230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
4002e1947a5SStefano Zampini {
4012e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
40228f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
4032e1947a5SStefano Zampini   PetscErrorCode ierr;
4042e1947a5SStefano Zampini 
4052e1947a5SStefano Zampini   PetscFunctionBegin;
4066c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
40728f4e0baSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
40828f4e0baSStefano Zampini     ierr = MatISComputeSF_Private(B);CHKERRQ(ierr);
40928f4e0baSStefano Zampini   }
4102e1947a5SStefano Zampini   if (!d_nnz) {
41128f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nz;
4122e1947a5SStefano Zampini   } else {
41328f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
4142e1947a5SStefano Zampini   }
4152e1947a5SStefano Zampini   if (!o_nnz) {
41628f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nz;
4172e1947a5SStefano Zampini   } else {
41828f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
4192e1947a5SStefano Zampini   }
42028f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
42128f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
42228f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
42328f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
42428f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves;i++) {
42528f4e0baSStefano Zampini     matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
4262e1947a5SStefano Zampini   }
42728f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
42828f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
42928f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
4302e1947a5SStefano Zampini   }
43128f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
43228f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
43328f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
4342e1947a5SStefano Zampini   }
43528f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
4362e1947a5SStefano Zampini   PetscFunctionReturn(0);
4372e1947a5SStefano Zampini }
438b4319ba4SBarry Smith 
439b4319ba4SBarry Smith #undef __FUNCT__
4403927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
4413927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
4423927de2eSStefano Zampini {
4433927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
4443927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
445ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
4463927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
4473927de2eSStefano Zampini   PetscInt        lrows,lcols;
4483927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
4493927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
4503927de2eSStefano Zampini   PetscBool       isdense,issbaij;
4513927de2eSStefano Zampini   PetscErrorCode  ierr;
4523927de2eSStefano Zampini 
4533927de2eSStefano Zampini   PetscFunctionBegin;
4543927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
4553927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
4563927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
4573927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
4583927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
4593927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
460ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
461ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
4627230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
463ecf5a873SStefano Zampini   } else {
464ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
465ecf5a873SStefano Zampini   }
466ecf5a873SStefano Zampini 
4673927de2eSStefano Zampini   if (issbaij) {
4683927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
4693927de2eSStefano Zampini   }
4703927de2eSStefano Zampini   /*
471ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
4723927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
4733927de2eSStefano Zampini   */
4743927de2eSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
4753927de2eSStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
4763927de2eSStefano Zampini   }
4773927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
4783927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
4793927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
4803927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
4813927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
4823927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
4833927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
4843927de2eSStefano Zampini       row_ownership[j] = i;
4853927de2eSStefano Zampini     }
4863927de2eSStefano Zampini   }
4877230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
4883927de2eSStefano Zampini 
4893927de2eSStefano Zampini   /*
4903927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
4913927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
4923927de2eSStefano Zampini   */
4933927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
4943927de2eSStefano Zampini   /* preallocation as a MATAIJ */
4953927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
4963927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
497ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
4983927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
4993927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
500ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
5013927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
5023927de2eSStefano Zampini           my_dnz[i] += 1;
5033927de2eSStefano Zampini         } else { /* offdiag block */
5043927de2eSStefano Zampini           my_onz[i] += 1;
5053927de2eSStefano Zampini         }
5063927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
5073927de2eSStefano Zampini         if (i != j) {
5083927de2eSStefano Zampini           owner = row_ownership[index_col];
5093927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
5103927de2eSStefano Zampini             my_dnz[j] += 1;
5113927de2eSStefano Zampini           } else {
5123927de2eSStefano Zampini             my_onz[j] += 1;
5133927de2eSStefano Zampini           }
5143927de2eSStefano Zampini         }
5153927de2eSStefano Zampini       }
5163927de2eSStefano Zampini     }
517ecf5a873SStefano Zampini   } else { /* TODO: this could be optimized using MatGetRowIJ */
5183927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
5193927de2eSStefano Zampini       const PetscInt *cols;
520ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
5213927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
5223927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
5233927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
524ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
5253927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
5263927de2eSStefano Zampini           my_dnz[i] += 1;
5273927de2eSStefano Zampini         } else { /* offdiag block */
5283927de2eSStefano Zampini           my_onz[i] += 1;
5293927de2eSStefano Zampini         }
5303927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
531d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
5323927de2eSStefano Zampini           owner = row_ownership[index_col];
5333927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
534d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
5353927de2eSStefano Zampini           } else {
536d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
5373927de2eSStefano Zampini           }
5383927de2eSStefano Zampini         }
5393927de2eSStefano Zampini       }
5403927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
5413927de2eSStefano Zampini     }
5423927de2eSStefano Zampini   }
543ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
544ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
5457230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
546ecf5a873SStefano Zampini   }
5473927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
548ecf5a873SStefano Zampini 
549ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
5503927de2eSStefano Zampini   if (maxreduce) {
5513927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
5523927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
5533927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
5543927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
5553927de2eSStefano Zampini   } else {
5563927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
5573927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
5583927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
5593927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
5603927de2eSStefano Zampini   }
5613927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
5623927de2eSStefano Zampini 
5633927de2eSStefano Zampini   /* Resize preallocation if overestimated */
5643927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
5653927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
5663927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
5673927de2eSStefano Zampini   }
5683927de2eSStefano Zampini   /* set preallocation */
5693927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
5703927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
5713927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
5723927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
5733927de2eSStefano Zampini   }
5743927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
5753927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
5763927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
5773927de2eSStefano Zampini   if (issbaij) {
5783927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
5793927de2eSStefano Zampini   }
5803927de2eSStefano Zampini   PetscFunctionReturn(0);
5813927de2eSStefano Zampini }
5823927de2eSStefano Zampini 
5833927de2eSStefano Zampini #undef __FUNCT__
584b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
5857230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
586b7ce53b6SStefano Zampini {
587b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
588d9a9e74cSStefano Zampini   Mat            local_mat;
589b7ce53b6SStefano Zampini   /* info on mat */
5903cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
591b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
592686e3a49SStefano Zampini   PetscBool      isdense,issbaij,isseqaij;
5937c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
594b7ce53b6SStefano Zampini   /* values insertion */
595b7ce53b6SStefano Zampini   PetscScalar    *array;
596b7ce53b6SStefano Zampini   /* work */
597b7ce53b6SStefano Zampini   PetscErrorCode ierr;
598b7ce53b6SStefano Zampini 
599b7ce53b6SStefano Zampini   PetscFunctionBegin;
600b7ce53b6SStefano Zampini   /* get info from mat */
6017c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
6027c03b4e8SStefano Zampini   if (nsubdomains == 1) {
6037c03b4e8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
6047c03b4e8SStefano Zampini       ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&(*M));CHKERRQ(ierr);
6057c03b4e8SStefano Zampini     } else {
6067c03b4e8SStefano Zampini       ierr = MatCopy(matis->A,*M,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
6077c03b4e8SStefano Zampini     }
6087c03b4e8SStefano Zampini     PetscFunctionReturn(0);
6097c03b4e8SStefano Zampini   }
610b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
611b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
6123cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
613b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
614b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
615686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
616b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
617b7ce53b6SStefano Zampini 
618b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
619b7ce53b6SStefano Zampini     MatType     new_mat_type;
6203927de2eSStefano Zampini     PetscBool   issbaij_red;
621b7ce53b6SStefano Zampini 
622b7ce53b6SStefano Zampini     /* determining new matrix type */
623b2566f29SBarry Smith     ierr = MPIU_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
624b7ce53b6SStefano Zampini     if (issbaij_red) {
625b7ce53b6SStefano Zampini       new_mat_type = MATSBAIJ;
626b7ce53b6SStefano Zampini     } else {
627b7ce53b6SStefano Zampini       if (bs>1) {
628b7ce53b6SStefano Zampini         new_mat_type = MATBAIJ;
629b7ce53b6SStefano Zampini       } else {
630b7ce53b6SStefano Zampini         new_mat_type = MATAIJ;
631b7ce53b6SStefano Zampini       }
632b7ce53b6SStefano Zampini     }
633b7ce53b6SStefano Zampini 
6343927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
6353cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
6363927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
6373927de2eSStefano Zampini     ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr);
6383927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
639b7ce53b6SStefano Zampini   } else {
6403cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
641b7ce53b6SStefano Zampini     /* some checks */
642b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
643b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
6443cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
6456c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
6466c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
6476c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
6486c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
6496c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
650b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
651b7ce53b6SStefano Zampini   }
652d9a9e74cSStefano Zampini 
653d9a9e74cSStefano Zampini   if (issbaij) {
654d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
655d9a9e74cSStefano Zampini   } else {
656d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
657d9a9e74cSStefano Zampini     local_mat = matis->A;
658d9a9e74cSStefano Zampini   }
659686e3a49SStefano Zampini 
660b7ce53b6SStefano Zampini   /* Set values */
661ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
662b7ce53b6SStefano Zampini   if (isdense) { /* special case for dense local matrices */
663ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
664ecf5a873SStefano Zampini 
665ecf5a873SStefano Zampini     if (local_rows != local_cols) {
666ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
667ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
668ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
669ecf5a873SStefano Zampini     } else {
670ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
671ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
672ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
673ecf5a873SStefano Zampini     }
674b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
675d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
676ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
677d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
678ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
679ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
680ecf5a873SStefano Zampini     } else {
681ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
682ecf5a873SStefano Zampini     }
683686e3a49SStefano Zampini   } else if (isseqaij) {
684ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
685686e3a49SStefano Zampini     PetscBool done;
686686e3a49SStefano Zampini 
687d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
6886c4ed002SBarry Smith     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
689d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
690686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
691ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
692686e3a49SStefano Zampini     }
693d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
6946c4ed002SBarry Smith     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
695d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
696686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
697ecf5a873SStefano Zampini     PetscInt i;
698c0962df8SStefano Zampini 
699686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
700686e3a49SStefano Zampini       PetscInt       j;
701ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
702686e3a49SStefano Zampini 
703ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
704ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
705ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
706686e3a49SStefano Zampini     }
707b7ce53b6SStefano Zampini   }
708b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
709d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
710b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
711b7ce53b6SStefano Zampini   if (isdense) {
712b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
713b7ce53b6SStefano Zampini   }
714b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
715b7ce53b6SStefano Zampini }
716b7ce53b6SStefano Zampini 
717b7ce53b6SStefano Zampini #undef __FUNCT__
718b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
719b7ce53b6SStefano Zampini /*@
720b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
721b7ce53b6SStefano Zampini 
722b7ce53b6SStefano Zampini   Input Parameter:
723b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
724b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
725b7ce53b6SStefano Zampini 
726b7ce53b6SStefano Zampini   Output Parameter:
727b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
728b7ce53b6SStefano Zampini 
729b7ce53b6SStefano Zampini   Level: developer
730b7ce53b6SStefano Zampini 
731eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
732b7ce53b6SStefano Zampini 
733b7ce53b6SStefano Zampini .seealso: MATIS
734b7ce53b6SStefano Zampini @*/
735b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
736b7ce53b6SStefano Zampini {
737b7ce53b6SStefano Zampini   PetscErrorCode ierr;
738b7ce53b6SStefano Zampini 
739b7ce53b6SStefano Zampini   PetscFunctionBegin;
740b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
741b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
742b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
743b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
744b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
745b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
7466c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
747b7ce53b6SStefano Zampini   }
748b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
749b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
750b7ce53b6SStefano Zampini }
751b7ce53b6SStefano Zampini 
752b7ce53b6SStefano Zampini #undef __FUNCT__
753ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
754ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
755ad6194a2SStefano Zampini {
756ad6194a2SStefano Zampini   PetscErrorCode ierr;
757ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
758ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
759ad6194a2SStefano Zampini   Mat            B,localmat;
760ad6194a2SStefano Zampini 
761ad6194a2SStefano Zampini   PetscFunctionBegin;
762ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
763ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
764ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
765e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
766ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
767ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
768b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
769ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
770ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
771ad6194a2SStefano Zampini   *newmat = B;
772ad6194a2SStefano Zampini   PetscFunctionReturn(0);
773ad6194a2SStefano Zampini }
774ad6194a2SStefano Zampini 
775ad6194a2SStefano Zampini #undef __FUNCT__
77669796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
777a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
77869796d55SStefano Zampini {
77969796d55SStefano Zampini   PetscErrorCode ierr;
78069796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
78169796d55SStefano Zampini   PetscBool      local_sym;
78269796d55SStefano Zampini 
78369796d55SStefano Zampini   PetscFunctionBegin;
78469796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
785b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
78669796d55SStefano Zampini   PetscFunctionReturn(0);
78769796d55SStefano Zampini }
78869796d55SStefano Zampini 
78969796d55SStefano Zampini #undef __FUNCT__
79069796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
791a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
79269796d55SStefano Zampini {
79369796d55SStefano Zampini   PetscErrorCode ierr;
79469796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
79569796d55SStefano Zampini   PetscBool      local_sym;
79669796d55SStefano Zampini 
79769796d55SStefano Zampini   PetscFunctionBegin;
79869796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
799b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
80069796d55SStefano Zampini   PetscFunctionReturn(0);
80169796d55SStefano Zampini }
80269796d55SStefano Zampini 
80369796d55SStefano Zampini #undef __FUNCT__
804b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
805a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
806b4319ba4SBarry Smith {
807dfbe8321SBarry Smith   PetscErrorCode ierr;
808b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
809b4319ba4SBarry Smith 
810b4319ba4SBarry Smith   PetscFunctionBegin;
8116bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
812e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
813e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
8146bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
8156bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
816a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
817a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
818a8116848SStefano Zampini   if (b->sf != b->csf) {
819a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
820a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
821a8116848SStefano Zampini   }
82228f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
82328f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
824bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
825dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
826bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
827b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
828b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
8292e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
830b4319ba4SBarry Smith   PetscFunctionReturn(0);
831b4319ba4SBarry Smith }
832b4319ba4SBarry Smith 
833b4319ba4SBarry Smith #undef __FUNCT__
834b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
835a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
836b4319ba4SBarry Smith {
837dfbe8321SBarry Smith   PetscErrorCode ierr;
838b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
839b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
840b4319ba4SBarry Smith 
841b4319ba4SBarry Smith   PetscFunctionBegin;
842b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
843e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
844e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
845b4319ba4SBarry Smith 
846b4319ba4SBarry Smith   /* multiply the local matrix */
847b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
848b4319ba4SBarry Smith 
849b4319ba4SBarry Smith   /* scatter product back into global memory */
8502dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
851e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
852e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
853b4319ba4SBarry Smith   PetscFunctionReturn(0);
854b4319ba4SBarry Smith }
855b4319ba4SBarry Smith 
856b4319ba4SBarry Smith #undef __FUNCT__
8572e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
858a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
8592e74eeadSLisandro Dalcin {
860650997f4SStefano Zampini   Vec            temp_vec;
8612e74eeadSLisandro Dalcin   PetscErrorCode ierr;
8622e74eeadSLisandro Dalcin 
8632e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
864650997f4SStefano Zampini   if (v3 != v2) {
865650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
866650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
867650997f4SStefano Zampini   } else {
868650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
869650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
870650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
871650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
872650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
873650997f4SStefano Zampini   }
8742e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
8752e74eeadSLisandro Dalcin }
8762e74eeadSLisandro Dalcin 
8772e74eeadSLisandro Dalcin #undef __FUNCT__
8782e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
879a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
8802e74eeadSLisandro Dalcin {
8812e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
8822e74eeadSLisandro Dalcin   PetscErrorCode ierr;
8832e74eeadSLisandro Dalcin 
884e176bc59SStefano Zampini   PetscFunctionBegin;
8852e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
886e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
887e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8882e74eeadSLisandro Dalcin 
8892e74eeadSLisandro Dalcin   /* multiply the local matrix */
890e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
8912e74eeadSLisandro Dalcin 
8922e74eeadSLisandro Dalcin   /* scatter product back into global vector */
893e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
894e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
895e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8962e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
8972e74eeadSLisandro Dalcin }
8982e74eeadSLisandro Dalcin 
8992e74eeadSLisandro Dalcin #undef __FUNCT__
9002e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
901a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
9022e74eeadSLisandro Dalcin {
903650997f4SStefano Zampini   Vec            temp_vec;
9042e74eeadSLisandro Dalcin   PetscErrorCode ierr;
9052e74eeadSLisandro Dalcin 
9062e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
907650997f4SStefano Zampini   if (v3 != v2) {
908650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
909650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
910650997f4SStefano Zampini   } else {
911650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
912650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
913650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
914650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
915650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
916650997f4SStefano Zampini   }
9172e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
9182e74eeadSLisandro Dalcin }
9192e74eeadSLisandro Dalcin 
9202e74eeadSLisandro Dalcin #undef __FUNCT__
921b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
922a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
923b4319ba4SBarry Smith {
924b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
925dfbe8321SBarry Smith   PetscErrorCode ierr;
926b4319ba4SBarry Smith   PetscViewer    sviewer;
927b4319ba4SBarry Smith 
928b4319ba4SBarry Smith   PetscFunctionBegin;
9293f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
930b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
9313f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
9326e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
933b4319ba4SBarry Smith   PetscFunctionReturn(0);
934b4319ba4SBarry Smith }
935b4319ba4SBarry Smith 
936b4319ba4SBarry Smith #undef __FUNCT__
937b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
938a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
939b4319ba4SBarry Smith {
940dfbe8321SBarry Smith   PetscErrorCode ierr;
941e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
942b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
943b4319ba4SBarry Smith   IS             from,to;
944e176bc59SStefano Zampini   Vec            cglobal,rglobal;
945b4319ba4SBarry Smith 
946b4319ba4SBarry Smith   PetscFunctionBegin;
947784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
948e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
9493bbff08aSStefano Zampini   /* Destroy any previous data */
95070cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
95170cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
952e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
953e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
9541c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
95528f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
95628f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
9573bbff08aSStefano Zampini 
9583bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
959fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
960fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
961fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
962fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
963b4319ba4SBarry Smith 
964b4319ba4SBarry Smith   /* Create the local matrix A */
965e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
966e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
967e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
968e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
969f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
970e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
971e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
972e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
973ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
974ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
975b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
976b4319ba4SBarry Smith 
977f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
978b4319ba4SBarry Smith     /* Create the local work vectors */
9793bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
980b4319ba4SBarry Smith 
981e176bc59SStefano Zampini     /* setup the global to local scatters */
982e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
983e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
984784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
985e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
986e176bc59SStefano Zampini     if (rmapping != cmapping) {
987e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
988e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
989e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
990e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
991e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
992e176bc59SStefano Zampini     } else {
993e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
994e176bc59SStefano Zampini       is->cctx = is->rctx;
995e176bc59SStefano Zampini     }
996e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
997e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
9986bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
9996bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1000f26d0771SStefano Zampini   }
100148ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1002b4319ba4SBarry Smith   PetscFunctionReturn(0);
1003b4319ba4SBarry Smith }
1004b4319ba4SBarry Smith 
10052e74eeadSLisandro Dalcin #undef __FUNCT__
10062e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
1007a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
10082e74eeadSLisandro Dalcin {
10092e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
10102e74eeadSLisandro Dalcin   PetscErrorCode ierr;
101197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
101297563a80SStefano Zampini   PetscInt       i,zm,zn;
101397563a80SStefano Zampini #endif
1014f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
10152e74eeadSLisandro Dalcin 
10162e74eeadSLisandro Dalcin   PetscFunctionBegin;
10172e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1018f26d0771SStefano Zampini   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);
101997563a80SStefano Zampini   /* count negative indices */
102097563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
102197563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
10222e74eeadSLisandro Dalcin #endif
102397563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
102497563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
102597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
102697563a80SStefano Zampini   /* count negative indices (should be the same as before) */
102797563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
102897563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
102997563a80SStefano Zampini   if (zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
103097563a80SStefano Zampini   if (zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
103197563a80SStefano Zampini #endif
10322e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
10332e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
10342e74eeadSLisandro Dalcin }
10352e74eeadSLisandro Dalcin 
1036b4319ba4SBarry Smith #undef __FUNCT__
103797563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS"
1038a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
103997563a80SStefano Zampini {
104097563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
104197563a80SStefano Zampini   PetscErrorCode ierr;
104297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
104397563a80SStefano Zampini   PetscInt       i,zm,zn;
104497563a80SStefano Zampini #endif
1045f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
104697563a80SStefano Zampini 
104797563a80SStefano Zampini   PetscFunctionBegin;
104897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1049f26d0771SStefano Zampini   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);
105097563a80SStefano Zampini   /* count negative indices */
105197563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
105297563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
105397563a80SStefano Zampini #endif
105497563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
105597563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
105697563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
105797563a80SStefano Zampini   /* count negative indices (should be the same as before) */
105897563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
105997563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
106097563a80SStefano Zampini   if (zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
106197563a80SStefano Zampini   if (zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
106297563a80SStefano Zampini #endif
106397563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
106497563a80SStefano Zampini   PetscFunctionReturn(0);
106597563a80SStefano Zampini }
106697563a80SStefano Zampini 
106797563a80SStefano Zampini #undef __FUNCT__
1068b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
1069a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1070b4319ba4SBarry Smith {
1071dfbe8321SBarry Smith   PetscErrorCode ierr;
1072b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1073b4319ba4SBarry Smith 
1074b4319ba4SBarry Smith   PetscFunctionBegin;
1075b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1076b4319ba4SBarry Smith   PetscFunctionReturn(0);
1077b4319ba4SBarry Smith }
1078b4319ba4SBarry Smith 
1079b4319ba4SBarry Smith #undef __FUNCT__
1080f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
1081a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1082f0006bf2SLisandro Dalcin {
1083f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1084f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1085f0006bf2SLisandro Dalcin 
1086f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1087f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1088f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1089f0006bf2SLisandro Dalcin }
1090f0006bf2SLisandro Dalcin 
1091f0006bf2SLisandro Dalcin #undef __FUNCT__
10922e74eeadSLisandro Dalcin #define __FUNCT__ "MatZeroRows_IS"
1093a8116848SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
10942e74eeadSLisandro Dalcin {
10956e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
10966e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
10976e520ac8SStefano Zampini   PetscInt       *lrows;
10982e74eeadSLisandro Dalcin   PetscErrorCode ierr;
10992e74eeadSLisandro Dalcin 
11002e74eeadSLisandro Dalcin   PetscFunctionBegin;
11016e520ac8SStefano Zampini   /* get locally owned rows */
11026e520ac8SStefano Zampini   ierr = MatZeroRowsMapLocal_Private(A,n,rows,&len,&lrows);CHKERRQ(ierr);
11036e520ac8SStefano Zampini   /* fix right hand side if needed */
11046e520ac8SStefano Zampini   if (x && b) {
11056e520ac8SStefano Zampini     const PetscScalar *xx;
11066e520ac8SStefano Zampini     PetscScalar       *bb;
11076e520ac8SStefano Zampini 
11086e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
11096e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
11106e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
11116e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
11126e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
11132e74eeadSLisandro Dalcin   }
11146e520ac8SStefano Zampini   /* get rows associated to the local matrices */
11156e520ac8SStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
11166e520ac8SStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
11176e520ac8SStefano Zampini   }
11186e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
11196e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
11206e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
11216e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
11226e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
11236e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
11246e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
11256e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
11266e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
11277230de76SStefano Zampini   ierr = MatISZeroRowsLocal_Private(A,nr,lrows,diag);CHKERRQ(ierr);
11286e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
11292e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
11302e74eeadSLisandro Dalcin }
11312e74eeadSLisandro Dalcin 
11322e74eeadSLisandro Dalcin #undef __FUNCT__
11337230de76SStefano Zampini #define __FUNCT__ "MatISZeroRowsLocal_Private"
11347230de76SStefano Zampini static PetscErrorCode MatISZeroRowsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag)
1135b4319ba4SBarry Smith {
1136b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1137dfbe8321SBarry Smith   PetscErrorCode ierr;
1138b4319ba4SBarry Smith 
1139b4319ba4SBarry Smith   PetscFunctionBegin;
11406e520ac8SStefano Zampini   if (diag != 0.) {
1141b4319ba4SBarry Smith     /*
1142b4319ba4SBarry Smith        Set up is->x as a "counting vector". This is in order to MatMult_IS
1143b4319ba4SBarry Smith        work properly in the interface nodes.
1144b4319ba4SBarry Smith     */
1145b4319ba4SBarry Smith     Vec counter;
1146e176bc59SStefano Zampini     ierr = MatCreateVecs(A,NULL,&counter);CHKERRQ(ierr);
1147e176bc59SStefano Zampini     ierr = VecSet(counter,0.);CHKERRQ(ierr);
1148e176bc59SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
1149e176bc59SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1150e176bc59SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1151e176bc59SStefano Zampini     ierr = VecScatterBegin(is->rctx,counter,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1152e176bc59SStefano Zampini     ierr = VecScatterEnd(is->rctx,counter,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11536bf464f9SBarry Smith     ierr = VecDestroy(&counter);CHKERRQ(ierr);
1154b4319ba4SBarry Smith   }
11552b404112SStefano Zampini 
1156958c9bccSBarry Smith   if (!n) {
1157b4319ba4SBarry Smith     is->pure_neumann = PETSC_TRUE;
1158b4319ba4SBarry Smith   } else {
11597230de76SStefano Zampini     PetscInt i;
1160b4319ba4SBarry Smith     is->pure_neumann = PETSC_FALSE;
11612205254eSKarl Rupp 
11622b40b63fSBarry Smith     ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
11636e520ac8SStefano Zampini     if (diag != 0.) {
11646e520ac8SStefano Zampini       const PetscScalar *array;
11656e520ac8SStefano Zampini       ierr = VecGetArrayRead(is->y,&array);CHKERRQ(ierr);
1166b4319ba4SBarry Smith       for (i=0; i<n; i++) {
1167f4df32b1SMatthew Knepley         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1168b4319ba4SBarry Smith       }
11696e520ac8SStefano Zampini       ierr = VecRestoreArrayRead(is->y,&array);CHKERRQ(ierr);
11706e520ac8SStefano Zampini     }
1171b4319ba4SBarry Smith     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1172b4319ba4SBarry Smith     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1173b4319ba4SBarry Smith   }
1174b4319ba4SBarry Smith   PetscFunctionReturn(0);
1175b4319ba4SBarry Smith }
1176b4319ba4SBarry Smith 
1177b4319ba4SBarry Smith #undef __FUNCT__
1178b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
1179a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1180b4319ba4SBarry Smith {
1181b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1182dfbe8321SBarry Smith   PetscErrorCode ierr;
1183b4319ba4SBarry Smith 
1184b4319ba4SBarry Smith   PetscFunctionBegin;
1185b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1186b4319ba4SBarry Smith   PetscFunctionReturn(0);
1187b4319ba4SBarry Smith }
1188b4319ba4SBarry Smith 
1189b4319ba4SBarry Smith #undef __FUNCT__
1190b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
1191a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1192b4319ba4SBarry Smith {
1193b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1194dfbe8321SBarry Smith   PetscErrorCode ierr;
1195b4319ba4SBarry Smith 
1196b4319ba4SBarry Smith   PetscFunctionBegin;
1197b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1198b4319ba4SBarry Smith   PetscFunctionReturn(0);
1199b4319ba4SBarry Smith }
1200b4319ba4SBarry Smith 
1201b4319ba4SBarry Smith #undef __FUNCT__
1202b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
1203a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1204b4319ba4SBarry Smith {
1205b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1206b4319ba4SBarry Smith 
1207b4319ba4SBarry Smith   PetscFunctionBegin;
1208b4319ba4SBarry Smith   *local = is->A;
1209b4319ba4SBarry Smith   PetscFunctionReturn(0);
1210b4319ba4SBarry Smith }
1211b4319ba4SBarry Smith 
1212b4319ba4SBarry Smith #undef __FUNCT__
1213b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
1214b4319ba4SBarry Smith /*@
1215b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1216b4319ba4SBarry Smith 
1217b4319ba4SBarry Smith   Input Parameter:
1218b4319ba4SBarry Smith .  mat - the matrix
1219b4319ba4SBarry Smith 
1220b4319ba4SBarry Smith   Output Parameter:
1221eb82efa4SStefano Zampini .  local - the local matrix
1222b4319ba4SBarry Smith 
1223b4319ba4SBarry Smith   Level: advanced
1224b4319ba4SBarry Smith 
1225b4319ba4SBarry Smith   Notes:
1226b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1227b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1228b4319ba4SBarry Smith   of the MatSetValues() operation.
1229b4319ba4SBarry Smith 
1230b4319ba4SBarry Smith .seealso: MATIS
1231b4319ba4SBarry Smith @*/
12327087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1233b4319ba4SBarry Smith {
12344ac538c5SBarry Smith   PetscErrorCode ierr;
1235b4319ba4SBarry Smith 
1236b4319ba4SBarry Smith   PetscFunctionBegin;
12370700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1238b4319ba4SBarry Smith   PetscValidPointer(local,2);
12394ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1240b4319ba4SBarry Smith   PetscFunctionReturn(0);
1241b4319ba4SBarry Smith }
1242b4319ba4SBarry Smith 
12433b03a366Sstefano_zampini #undef __FUNCT__
12443b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
1245a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
12463b03a366Sstefano_zampini {
12473b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
12483b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
12493b03a366Sstefano_zampini   PetscErrorCode ierr;
12503b03a366Sstefano_zampini 
12513b03a366Sstefano_zampini   PetscFunctionBegin;
12524e4c7dbeSStefano Zampini   if (is->A) {
12533b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
12543b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1255f23aa3ddSBarry Smith     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)\n",orows,ocols,nrows,ncols);
12564e4c7dbeSStefano Zampini   }
12573b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
12583b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
12593b03a366Sstefano_zampini   is->A = local;
12603b03a366Sstefano_zampini   PetscFunctionReturn(0);
12613b03a366Sstefano_zampini }
12623b03a366Sstefano_zampini 
12633b03a366Sstefano_zampini #undef __FUNCT__
12643b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
12653b03a366Sstefano_zampini /*@
1266eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
12673b03a366Sstefano_zampini 
12683b03a366Sstefano_zampini   Input Parameter:
12693b03a366Sstefano_zampini .  mat - the matrix
1270eb82efa4SStefano Zampini .  local - the local matrix
12713b03a366Sstefano_zampini 
12723b03a366Sstefano_zampini   Output Parameter:
12733b03a366Sstefano_zampini 
12743b03a366Sstefano_zampini   Level: advanced
12753b03a366Sstefano_zampini 
12763b03a366Sstefano_zampini   Notes:
12773b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
12783b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
12793b03a366Sstefano_zampini 
12803b03a366Sstefano_zampini .seealso: MATIS
12813b03a366Sstefano_zampini @*/
12823b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
12833b03a366Sstefano_zampini {
12843b03a366Sstefano_zampini   PetscErrorCode ierr;
12853b03a366Sstefano_zampini 
12863b03a366Sstefano_zampini   PetscFunctionBegin;
12873b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1288b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
12893b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
12903b03a366Sstefano_zampini   PetscFunctionReturn(0);
12913b03a366Sstefano_zampini }
12923b03a366Sstefano_zampini 
12936726f965SBarry Smith #undef __FUNCT__
12946726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
1295a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
12966726f965SBarry Smith {
12976726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
12986726f965SBarry Smith   PetscErrorCode ierr;
12996726f965SBarry Smith 
13006726f965SBarry Smith   PetscFunctionBegin;
13016726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
13026726f965SBarry Smith   PetscFunctionReturn(0);
13036726f965SBarry Smith }
13046726f965SBarry Smith 
13056726f965SBarry Smith #undef __FUNCT__
13062e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
1307a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
13082e74eeadSLisandro Dalcin {
13092e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
13102e74eeadSLisandro Dalcin   PetscErrorCode ierr;
13112e74eeadSLisandro Dalcin 
13122e74eeadSLisandro Dalcin   PetscFunctionBegin;
13132e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
13142e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
13152e74eeadSLisandro Dalcin }
13162e74eeadSLisandro Dalcin 
13172e74eeadSLisandro Dalcin #undef __FUNCT__
13182e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
1319a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
13202e74eeadSLisandro Dalcin {
13212e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
13222e74eeadSLisandro Dalcin   PetscErrorCode ierr;
13232e74eeadSLisandro Dalcin 
13242e74eeadSLisandro Dalcin   PetscFunctionBegin;
13252e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
1326e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
13272e74eeadSLisandro Dalcin 
13282e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
13292e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
1330e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1331e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13322e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
13332e74eeadSLisandro Dalcin }
13342e74eeadSLisandro Dalcin 
13352e74eeadSLisandro Dalcin #undef __FUNCT__
13366726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
1337a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
13386726f965SBarry Smith {
13396726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
13406726f965SBarry Smith   PetscErrorCode ierr;
13416726f965SBarry Smith 
13426726f965SBarry Smith   PetscFunctionBegin;
13434e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
13446726f965SBarry Smith   PetscFunctionReturn(0);
13456726f965SBarry Smith }
13466726f965SBarry Smith 
1347284134d9SBarry Smith #undef __FUNCT__
1348f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS"
1349f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
1350f26d0771SStefano Zampini {
1351f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
1352f26d0771SStefano Zampini   Mat_IS         *x;
1353f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1354f26d0771SStefano Zampini   PetscBool      ismatis;
1355f26d0771SStefano Zampini #endif
1356f26d0771SStefano Zampini   PetscErrorCode ierr;
1357f26d0771SStefano Zampini 
1358f26d0771SStefano Zampini   PetscFunctionBegin;
1359f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1360f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
1361f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
1362f26d0771SStefano Zampini #endif
1363f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
1364f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
1365f26d0771SStefano Zampini   PetscFunctionReturn(0);
1366f26d0771SStefano Zampini }
1367f26d0771SStefano Zampini 
1368f26d0771SStefano Zampini #undef __FUNCT__
1369f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS"
1370f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
1371f26d0771SStefano Zampini {
1372f26d0771SStefano Zampini   Mat                    lA;
1373f26d0771SStefano Zampini   Mat_IS                 *matis;
1374f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
1375f26d0771SStefano Zampini   IS                     is;
1376f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
1377f26d0771SStefano Zampini   PetscInt               nrg;
1378f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
1379f26d0771SStefano Zampini   PetscErrorCode         ierr;
1380f26d0771SStefano Zampini 
1381f26d0771SStefano Zampini   PetscFunctionBegin;
1382f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1383f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
1384f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
1385f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
1386f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1387f26d0771SStefano Zampini   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\n",i,rl[i],nrg);
1388f26d0771SStefano Zampini #endif
1389f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
1390f26d0771SStefano Zampini   /* map from [0,nrl) to row */
1391f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
1392f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1393f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
1394f26d0771SStefano Zampini #else
1395f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
1396f26d0771SStefano Zampini #endif
1397f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
1398f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1399f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1400f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1401f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
1402f26d0771SStefano Zampini   /* compute new l2g map for columns */
1403f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
1404f26d0771SStefano Zampini     const PetscInt *cg,*cl;
1405f26d0771SStefano Zampini     PetscInt       ncg;
1406f26d0771SStefano Zampini     PetscInt       ncl;
1407f26d0771SStefano Zampini 
1408f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1409f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
1410f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
1411f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
1412f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1413f26d0771SStefano Zampini     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\n",i,cl[i],ncg);
1414f26d0771SStefano Zampini #endif
1415f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
1416f26d0771SStefano Zampini     /* map from [0,ncl) to col */
1417f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
1418f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1419f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
1420f26d0771SStefano Zampini #else
1421f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
1422f26d0771SStefano Zampini #endif
1423f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
1424f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1425f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1426f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1427f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1428f26d0771SStefano Zampini   } else {
1429f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
1430f26d0771SStefano Zampini     cl2g = rl2g;
1431f26d0771SStefano Zampini   }
1432f26d0771SStefano Zampini   /* create the MATIS submatrix */
1433f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
1434f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
1435f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1436f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
1437*b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
1438f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
1439f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
1440f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1441f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
1442f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
1443f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1444f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1445f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1446f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1447f26d0771SStefano Zampini   /* remove unsupported ops */
1448f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1449f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
1450f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
1451f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
1452f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
1453f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
1454f26d0771SStefano Zampini   PetscFunctionReturn(0);
1455f26d0771SStefano Zampini }
1456f26d0771SStefano Zampini 
1457f26d0771SStefano Zampini #undef __FUNCT__
1458284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
1459284134d9SBarry Smith /*@
14603c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
1461284134d9SBarry Smith        process but not across processes.
1462284134d9SBarry Smith 
1463284134d9SBarry Smith    Input Parameters:
1464284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
1465e176bc59SStefano Zampini .     bs      - block size of the matrix
1466df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
1467e176bc59SStefano Zampini .     rmap    - local to global map for rows
1468e176bc59SStefano Zampini -     cmap    - local to global map for cols
1469284134d9SBarry Smith 
1470284134d9SBarry Smith    Output Parameter:
1471284134d9SBarry Smith .    A - the resulting matrix
1472284134d9SBarry Smith 
14738e6c10adSSatish Balay    Level: advanced
14748e6c10adSSatish Balay 
14753c212e90SHong Zhang    Notes: See MATIS for more details.
14763c212e90SHong Zhang           m and n are NOT related to the size of the map; they are the size of the part of the vector owned
1477e176bc59SStefano Zampini           by that process. The sizes of rmap and cmap define the size of the local matrices.
14783c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
1479284134d9SBarry Smith 
1480284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
1481284134d9SBarry Smith @*/
1482e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
1483284134d9SBarry Smith {
1484284134d9SBarry Smith   PetscErrorCode ierr;
1485284134d9SBarry Smith 
1486284134d9SBarry Smith   PetscFunctionBegin;
1487e176bc59SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mapping");
1488284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1489d3ee2243SStefano Zampini   ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
1490284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
1491284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
1492e176bc59SStefano Zampini   if (rmap && cmap) {
1493e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
1494e176bc59SStefano Zampini   } else if (!rmap) {
1495e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
1496e176bc59SStefano Zampini   } else {
1497e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
1498e176bc59SStefano Zampini   }
1499284134d9SBarry Smith   PetscFunctionReturn(0);
1500284134d9SBarry Smith }
1501284134d9SBarry Smith 
1502b4319ba4SBarry Smith /*MC
1503f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
1504b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
1505b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
1506b4319ba4SBarry Smith    product is handled "implicitly".
1507b4319ba4SBarry Smith 
1508b4319ba4SBarry Smith    Operations Provided:
15096726f965SBarry Smith +  MatMult()
15102e74eeadSLisandro Dalcin .  MatMultAdd()
15112e74eeadSLisandro Dalcin .  MatMultTranspose()
15122e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
15136726f965SBarry Smith .  MatZeroEntries()
15146726f965SBarry Smith .  MatSetOption()
15152e74eeadSLisandro Dalcin .  MatZeroRows()
15162e74eeadSLisandro Dalcin .  MatSetValues()
151797563a80SStefano Zampini .  MatSetValuesBlocked()
15186726f965SBarry Smith .  MatSetValuesLocal()
151997563a80SStefano Zampini .  MatSetValuesBlockedLocal()
15202e74eeadSLisandro Dalcin .  MatScale()
15212e74eeadSLisandro Dalcin .  MatGetDiagonal()
15222b404112SStefano Zampini .  MatMissingDiagonal()
15232b404112SStefano Zampini .  MatDuplicate()
15242b404112SStefano Zampini .  MatCopy()
1525f26d0771SStefano Zampini .  MatAXPY()
1526f26d0771SStefano Zampini .  MatGetSubMatrix()
1527f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
15286726f965SBarry Smith -  MatSetLocalToGlobalMapping()
1529b4319ba4SBarry Smith 
1530b4319ba4SBarry Smith    Options Database Keys:
1531b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
1532b4319ba4SBarry Smith 
1533b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
1534b4319ba4SBarry Smith 
1535b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
1536b4319ba4SBarry Smith 
1537b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
1538eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
1539b4319ba4SBarry Smith 
1540b4319ba4SBarry Smith   Level: advanced
1541b4319ba4SBarry Smith 
1542f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
1543b4319ba4SBarry Smith 
1544b4319ba4SBarry Smith M*/
1545b4319ba4SBarry Smith 
1546b4319ba4SBarry Smith #undef __FUNCT__
1547b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
15488cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
1549b4319ba4SBarry Smith {
1550dfbe8321SBarry Smith   PetscErrorCode ierr;
1551b4319ba4SBarry Smith   Mat_IS         *b;
1552b4319ba4SBarry Smith 
1553b4319ba4SBarry Smith   PetscFunctionBegin;
1554b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
1555b4319ba4SBarry Smith   A->data = (void*)b;
1556b4319ba4SBarry Smith 
1557e176bc59SStefano Zampini   /* matrix ops */
1558e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1559b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
15602e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
15612e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
15622e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
1563b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
1564b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
15652e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
156698921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
1567b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
1568f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
15692e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
1570b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
1571b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
1572b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
15736726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
15742e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
15752e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
15766726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
157769796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
157869796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
1579ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
15806bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
15812b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
1582659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
1583a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
1584f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
1585b4319ba4SBarry Smith 
1586b7ce53b6SStefano Zampini   /* special MATIS functions */
1587bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
1588bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
1589b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
15902e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
159117667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
1592b4319ba4SBarry Smith   PetscFunctionReturn(0);
1593b4319ba4SBarry Smith }
1594