xref: /petsc/src/mat/impls/is/matis.c (revision fd3a879c26e949fba644f5076a22f5da515220b8)
1b4319ba4SBarry Smith /*
2b4319ba4SBarry Smith     Creates a matrix class for using the Neumann-Neumann type preconditioners.
3b4319ba4SBarry Smith     This stores the matrices in globally unassembled form. Each processor
4b4319ba4SBarry Smith     assembles only its local Neumann problem and the parallel matrix vector
5b4319ba4SBarry Smith     product is handled "implicitly".
6b4319ba4SBarry Smith 
7b4319ba4SBarry Smith     Currently this allows for only one subdomain per processor.
8b4319ba4SBarry Smith */
9b4319ba4SBarry Smith 
10c6db04a5SJed Brown #include <../src/mat/impls/is/matis.h>      /*I "petscmat.h" I*/
1128f4e0baSStefano Zampini 
12f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
13f26d0771SStefano Zampini 
14a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat);
15a72627d2SStefano Zampini 
1628f4e0baSStefano Zampini #undef __FUNCT__
17d7f69cd0SStefano Zampini #define __FUNCT__ "MatTranspose_IS"
18d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
19d7f69cd0SStefano Zampini {
20d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
21d7f69cd0SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
22d7f69cd0SStefano Zampini   PetscBool              notset = PETSC_FALSE,cong = PETSC_TRUE;
23d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
24d7f69cd0SStefano Zampini 
25d7f69cd0SStefano Zampini   PetscFunctionBegin;
26d7f69cd0SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
27d7f69cd0SStefano Zampini     PetscBool rcong,ccong;
28d7f69cd0SStefano Zampini 
29d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr);
30d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr);
31fa520230SStefano Zampini     cong = (PetscBool)(rcong || ccong);
32d7f69cd0SStefano Zampini   }
33d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) {
34d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
35d7f69cd0SStefano Zampini   } else {
36d7f69cd0SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,&notset);CHKERRQ(ierr);
37d7f69cd0SStefano Zampini     C = *B;
38d7f69cd0SStefano Zampini   }
39d7f69cd0SStefano Zampini 
40d7f69cd0SStefano Zampini   if (!notset) {
41d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
42d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
43d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
44d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
45d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
46d7f69cd0SStefano Zampini   }
47d7f69cd0SStefano Zampini 
48d7f69cd0SStefano Zampini   /* perform local transposition */
49d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
50d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
51d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
52d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
53d7f69cd0SStefano Zampini 
54d7f69cd0SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55d7f69cd0SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
56d7f69cd0SStefano Zampini 
57d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
58d7f69cd0SStefano Zampini     if (!cong) {
59d7f69cd0SStefano Zampini       ierr = MatDestroy(B);CHKERRQ(ierr);
60d7f69cd0SStefano Zampini     }
61d7f69cd0SStefano Zampini     *B = C;
62d7f69cd0SStefano Zampini   } else {
63d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
64d7f69cd0SStefano Zampini   }
65d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
66d7f69cd0SStefano Zampini }
67d7f69cd0SStefano Zampini 
68d7f69cd0SStefano Zampini #undef __FUNCT__
693fd1c9e7SStefano Zampini #define __FUNCT__ "MatDiagonalSet_IS"
703fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
713fd1c9e7SStefano Zampini {
723fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
733fd1c9e7SStefano Zampini   PetscErrorCode ierr;
743fd1c9e7SStefano Zampini 
753fd1c9e7SStefano Zampini   PetscFunctionBegin;
763fd1c9e7SStefano Zampini   if (!D) { /* this code branch is used by MatShift_IS */
773fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
783fd1c9e7SStefano Zampini   } else {
793fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
803fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
813fd1c9e7SStefano Zampini   }
823fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
833fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
843fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
853fd1c9e7SStefano Zampini }
863fd1c9e7SStefano Zampini 
873fd1c9e7SStefano Zampini #undef __FUNCT__
883fd1c9e7SStefano Zampini #define __FUNCT__ "MatShift_IS"
893fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
903fd1c9e7SStefano Zampini {
913fd1c9e7SStefano Zampini   PetscErrorCode ierr;
923fd1c9e7SStefano Zampini 
933fd1c9e7SStefano Zampini   PetscFunctionBegin;
943fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
953fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
963fd1c9e7SStefano Zampini }
973fd1c9e7SStefano Zampini 
983fd1c9e7SStefano Zampini #undef __FUNCT__
99f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS"
100f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
101f26d0771SStefano Zampini {
102f26d0771SStefano Zampini   PetscErrorCode ierr;
103f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
104f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
105f26d0771SStefano Zampini 
106f26d0771SStefano Zampini   PetscFunctionBegin;
107f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
108f26d0771SStefano 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);
109f26d0771SStefano Zampini #endif
110f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
111f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
112f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
113f26d0771SStefano Zampini   PetscFunctionReturn(0);
114f26d0771SStefano Zampini }
115f26d0771SStefano Zampini 
116f26d0771SStefano Zampini #undef __FUNCT__
117f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS"
118f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
119f26d0771SStefano Zampini {
120f26d0771SStefano Zampini   PetscErrorCode ierr;
121f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
122f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
123f26d0771SStefano Zampini 
124f26d0771SStefano Zampini   PetscFunctionBegin;
125f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
126f26d0771SStefano 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);
127f26d0771SStefano Zampini #endif
128f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
129f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
130f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
131f26d0771SStefano Zampini   PetscFunctionReturn(0);
132f26d0771SStefano Zampini }
133f26d0771SStefano Zampini 
134f26d0771SStefano Zampini #undef __FUNCT__
135a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private"
136f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
137a8116848SStefano Zampini {
138a8116848SStefano Zampini   PetscInt      *owners = map->range;
139a8116848SStefano Zampini   PetscInt       n      = map->n;
140a8116848SStefano Zampini   PetscSF        sf;
141a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
142a8116848SStefano Zampini   PetscSFNode   *ridxs;
143a8116848SStefano Zampini   PetscMPIInt    rank;
144a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
145a8116848SStefano Zampini   PetscErrorCode ierr;
146a8116848SStefano Zampini 
147a8116848SStefano Zampini   PetscFunctionBegin;
148*fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
149a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
150a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
151a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
152a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
153a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
154a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
155a8116848SStefano Zampini     const PetscInt idx = idxs[r];
156a8116848SStefano 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);
157a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
158a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
159a8116848SStefano Zampini     }
160a8116848SStefano Zampini     ridxs[r].rank = p;
161a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
162a8116848SStefano Zampini   }
163a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
164a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
165a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
166a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
167f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
168a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
169f0ae7da4SStefano Zampini 
170f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
171a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
172a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
173a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
174a8116848SStefano Zampini     start -= cum;
175a8116848SStefano Zampini     cum = 0;
176a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
177a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
178a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
179a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
180a8116848SStefano Zampini   }
181a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
182a8116848SStefano Zampini   /* Compress and put in indices */
183a8116848SStefano Zampini   for (r = 0; r < n; ++r)
184a8116848SStefano Zampini     if (lidxs[r] >= 0) {
185a8116848SStefano Zampini       if (work) work[len] = work[r];
186a8116848SStefano Zampini       lidxs[len++] = r;
187a8116848SStefano Zampini     }
188a8116848SStefano Zampini   if (on) *on = len;
189a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
190a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
191a8116848SStefano Zampini   PetscFunctionReturn(0);
192a8116848SStefano Zampini }
193a8116848SStefano Zampini 
194a8116848SStefano Zampini #undef __FUNCT__
195a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS"
196a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
197a8116848SStefano Zampini {
198a8116848SStefano Zampini   Mat               locmat,newlocmat;
199a8116848SStefano Zampini   Mat_IS            *newmatis;
200a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
201a8116848SStefano Zampini   Vec               rtest,ltest;
202a8116848SStefano Zampini   const PetscScalar *array;
203a8116848SStefano Zampini #endif
204a8116848SStefano Zampini   const PetscInt    *idxs;
205a8116848SStefano Zampini   PetscInt          i,m,n;
206a8116848SStefano Zampini   PetscErrorCode    ierr;
207a8116848SStefano Zampini 
208a8116848SStefano Zampini   PetscFunctionBegin;
209a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
210a8116848SStefano Zampini     PetscBool ismatis;
211a8116848SStefano Zampini 
212a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
213a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
214a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
215a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
216a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
217a8116848SStefano Zampini   }
218a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
219a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
220a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
221a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
222a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
223a8116848SStefano Zampini   for (i=0;i<n;i++) {
224a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
225a8116848SStefano Zampini   }
226a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
227a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
228a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
229a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
230a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
231fd479f66SMatthew 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]));
232a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
233a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
234a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
235a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
236a8116848SStefano Zampini   for (i=0;i<n;i++) {
237a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
238a8116848SStefano Zampini   }
239a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
240a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
241a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
242a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
243a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
244fd479f66SMatthew 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]));
245a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
246a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
247a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
248a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
249a8116848SStefano Zampini #endif
250a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
251a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
252a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
253a8116848SStefano Zampini     IS                     is;
254a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
2556dd40735SStefano Zampini     PetscInt               ll,newloc;
256a8116848SStefano Zampini     MPI_Comm               comm;
257a8116848SStefano Zampini 
258a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
259a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
260a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
261a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
262a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
263a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
264a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
265a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
266f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
267a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
268a8116848SStefano Zampini     if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
269a8116848SStefano Zampini       ierr = MatISComputeSF_Private(mat);CHKERRQ(ierr);
270a8116848SStefano Zampini     }
271a8116848SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
272a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
273a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
274a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
275a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
276a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
277a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
278a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
279a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
280a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++)
281a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
282a8116848SStefano Zampini         lidxs[newloc] = i;
283a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
284a8116848SStefano Zampini       }
285a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
286a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
287a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
288a8116848SStefano Zampini     /* local is to extract local submatrix */
289a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
290a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
291a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
292a8116848SStefano Zampini       PetscBool cong;
293a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
294a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
295a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
296a8116848SStefano Zampini     }
297a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
298a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
299a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
300a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
301a8116848SStefano Zampini     } else {
302a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
303a8116848SStefano Zampini 
304a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
305a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
306f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
307a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
308a8116848SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
309a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
310a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
311a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
312a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
313a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
314a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
315a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
316a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
317a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++)
318a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
319a8116848SStefano Zampini           lidxs[newloc] = i;
320a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
321a8116848SStefano Zampini         }
322a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
323a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
324a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
325a8116848SStefano Zampini       /* local is to extract local submatrix */
326a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
327a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
328a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
329a8116848SStefano Zampini     }
330a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
331a8116848SStefano Zampini   } else {
332a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
333a8116848SStefano Zampini   }
334a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
335a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
336a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
337a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
338a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
339a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
340a8116848SStefano Zampini   }
341a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
342a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
343a8116848SStefano Zampini   PetscFunctionReturn(0);
344a8116848SStefano Zampini }
345a8116848SStefano Zampini 
346a8116848SStefano Zampini #undef __FUNCT__
3472b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS"
348a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
3492b404112SStefano Zampini {
3502b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
3512b404112SStefano Zampini   PetscBool      ismatis;
3522b404112SStefano Zampini   PetscErrorCode ierr;
3532b404112SStefano Zampini 
3542b404112SStefano Zampini   PetscFunctionBegin;
3552b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
3562b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
3572b404112SStefano Zampini   b = (Mat_IS*)B->data;
3582b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
3592b404112SStefano Zampini   PetscFunctionReturn(0);
3602b404112SStefano Zampini }
3612b404112SStefano Zampini 
3622b404112SStefano Zampini #undef __FUNCT__
3636bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS"
364a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
3656bd84002SStefano Zampini {
366527b2640SStefano Zampini   Vec               v;
367527b2640SStefano Zampini   const PetscScalar *array;
368527b2640SStefano Zampini   PetscInt          i,n;
3696bd84002SStefano Zampini   PetscErrorCode    ierr;
3706bd84002SStefano Zampini 
3716bd84002SStefano Zampini   PetscFunctionBegin;
372527b2640SStefano Zampini   *missing = PETSC_FALSE;
373527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
374527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
375527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
376527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
377527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
378527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
379527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
380527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
381527b2640SStefano Zampini   if (d) {
382527b2640SStefano Zampini     *d = -1;
383527b2640SStefano Zampini     if (*missing) {
384527b2640SStefano Zampini       PetscInt rstart;
385527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
386527b2640SStefano Zampini       *d = i+rstart;
387527b2640SStefano Zampini     }
388527b2640SStefano Zampini   }
3896bd84002SStefano Zampini   PetscFunctionReturn(0);
3906bd84002SStefano Zampini }
3916bd84002SStefano Zampini 
3926bd84002SStefano Zampini #undef __FUNCT__
39328f4e0baSStefano Zampini #define __FUNCT__ "MatISComputeSF_Private"
394a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat B)
39528f4e0baSStefano Zampini {
39628f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
39728f4e0baSStefano Zampini   const PetscInt *gidxs;
39828f4e0baSStefano Zampini   PetscErrorCode ierr;
39928f4e0baSStefano Zampini 
40028f4e0baSStefano Zampini   PetscFunctionBegin;
40128f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,&matis->sf_nleaves,NULL);CHKERRQ(ierr);
40228f4e0baSStefano Zampini   ierr = MatGetLocalSize(B,&matis->sf_nroots,NULL);CHKERRQ(ierr);
40328f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
4043bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
40528f4e0baSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,matis->sf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
4063bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
40728f4e0baSStefano Zampini   ierr = PetscMalloc2(matis->sf_nroots,&matis->sf_rootdata,matis->sf_nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
408a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
409a8116848SStefano Zampini     ierr = MatGetSize(matis->A,NULL,&matis->csf_nleaves);CHKERRQ(ierr);
410a8116848SStefano Zampini     ierr = MatGetLocalSize(B,NULL,&matis->csf_nroots);CHKERRQ(ierr);
411a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
412a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
413a8116848SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,matis->csf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
414a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
415a8116848SStefano Zampini     ierr = PetscMalloc2(matis->csf_nroots,&matis->csf_rootdata,matis->csf_nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
416a8116848SStefano Zampini   } else {
417a8116848SStefano Zampini     matis->csf = matis->sf;
418a8116848SStefano Zampini     matis->csf_nleaves = matis->sf_nleaves;
419a8116848SStefano Zampini     matis->csf_nroots = matis->sf_nroots;
420a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
421a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
422a8116848SStefano Zampini   }
42328f4e0baSStefano Zampini   PetscFunctionReturn(0);
42428f4e0baSStefano Zampini }
4252e1947a5SStefano Zampini 
4262e1947a5SStefano Zampini #undef __FUNCT__
4272e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
428eb82efa4SStefano Zampini /*@
429a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
430a88811baSStefano Zampini 
431a88811baSStefano Zampini    Collective on MPI_Comm
432a88811baSStefano Zampini 
433a88811baSStefano Zampini    Input Parameters:
434a88811baSStefano Zampini +  B - the matrix
435a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
436a88811baSStefano Zampini            (same value is used for all local rows)
437a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
438a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
439a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
440a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
441a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
442a88811baSStefano Zampini            the diagonal entry even if it is zero.
443a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
444a88811baSStefano Zampini            submatrix (same value is used for all local rows).
445a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
446a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
447a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
448a88811baSStefano Zampini            structure. The size of this array is equal to the number
449a88811baSStefano Zampini            of local rows, i.e 'm'.
450a88811baSStefano Zampini 
451a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
452a88811baSStefano Zampini 
453a88811baSStefano Zampini    Level: intermediate
454a88811baSStefano Zampini 
455a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
456a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
457a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
458a88811baSStefano Zampini 
459a88811baSStefano Zampini .keywords: matrix
460a88811baSStefano Zampini 
4613c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
462a88811baSStefano Zampini @*/
4632e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
4642e1947a5SStefano Zampini {
4652e1947a5SStefano Zampini   PetscErrorCode ierr;
4662e1947a5SStefano Zampini 
4672e1947a5SStefano Zampini   PetscFunctionBegin;
4682e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
4692e1947a5SStefano Zampini   PetscValidType(B,1);
4702e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
4712e1947a5SStefano Zampini   PetscFunctionReturn(0);
4722e1947a5SStefano Zampini }
4732e1947a5SStefano Zampini 
4742e1947a5SStefano Zampini #undef __FUNCT__
4752e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
4767230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
4772e1947a5SStefano Zampini {
4782e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
47928f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
4802e1947a5SStefano Zampini   PetscErrorCode ierr;
4812e1947a5SStefano Zampini 
4822e1947a5SStefano Zampini   PetscFunctionBegin;
4836c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
48428f4e0baSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
48528f4e0baSStefano Zampini     ierr = MatISComputeSF_Private(B);CHKERRQ(ierr);
48628f4e0baSStefano Zampini   }
4872e1947a5SStefano Zampini   if (!d_nnz) {
48828f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nz;
4892e1947a5SStefano Zampini   } else {
49028f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
4912e1947a5SStefano Zampini   }
4922e1947a5SStefano Zampini   if (!o_nnz) {
49328f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nz;
4942e1947a5SStefano Zampini   } else {
49528f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
4962e1947a5SStefano Zampini   }
49728f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
49828f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
49928f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
50028f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
50128f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves;i++) {
50228f4e0baSStefano Zampini     matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
5032e1947a5SStefano Zampini   }
50428f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
50528f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
50628f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
5072e1947a5SStefano Zampini   }
50828f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
50928f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
51028f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
5112e1947a5SStefano Zampini   }
51228f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
5132e1947a5SStefano Zampini   PetscFunctionReturn(0);
5142e1947a5SStefano Zampini }
515b4319ba4SBarry Smith 
516b4319ba4SBarry Smith #undef __FUNCT__
5173927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
5183927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
5193927de2eSStefano Zampini {
5203927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
5213927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
522ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
5233927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
5243927de2eSStefano Zampini   PetscInt        lrows,lcols;
5253927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
5263927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
5273927de2eSStefano Zampini   PetscBool       isdense,issbaij;
5283927de2eSStefano Zampini   PetscErrorCode  ierr;
5293927de2eSStefano Zampini 
5303927de2eSStefano Zampini   PetscFunctionBegin;
5313927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
5323927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
5333927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
5343927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
5353927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
5363927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
537ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
538ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
5397230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
540ecf5a873SStefano Zampini   } else {
541ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
542ecf5a873SStefano Zampini   }
543ecf5a873SStefano Zampini 
5443927de2eSStefano Zampini   if (issbaij) {
5453927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
5463927de2eSStefano Zampini   }
5473927de2eSStefano Zampini   /*
548ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
5493927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
5503927de2eSStefano Zampini   */
5513927de2eSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
5523927de2eSStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
5533927de2eSStefano Zampini   }
5543927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
5553927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
5563927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
5573927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
5583927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
5593927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
5603927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
5613927de2eSStefano Zampini       row_ownership[j] = i;
5623927de2eSStefano Zampini     }
5633927de2eSStefano Zampini   }
5647230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
5653927de2eSStefano Zampini 
5663927de2eSStefano Zampini   /*
5673927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
5683927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
5693927de2eSStefano Zampini   */
5703927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
5713927de2eSStefano Zampini   /* preallocation as a MATAIJ */
5723927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
5733927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
574ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
5753927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
5763927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
577ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
5783927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
5793927de2eSStefano Zampini           my_dnz[i] += 1;
5803927de2eSStefano Zampini         } else { /* offdiag block */
5813927de2eSStefano Zampini           my_onz[i] += 1;
5823927de2eSStefano Zampini         }
5833927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
5843927de2eSStefano Zampini         if (i != j) {
5853927de2eSStefano Zampini           owner = row_ownership[index_col];
5863927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
5873927de2eSStefano Zampini             my_dnz[j] += 1;
5883927de2eSStefano Zampini           } else {
5893927de2eSStefano Zampini             my_onz[j] += 1;
5903927de2eSStefano Zampini           }
5913927de2eSStefano Zampini         }
5923927de2eSStefano Zampini       }
5933927de2eSStefano Zampini     }
594bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
595bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
596bb1015c3SStefano Zampini     PetscBool      done;
597bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
598bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
599bb1015c3SStefano Zampini     jptr = jj;
600bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
601bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
602bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
603bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
604bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
605bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
606bb1015c3SStefano Zampini           my_dnz[i] += 1;
607bb1015c3SStefano Zampini         } else { /* offdiag block */
608bb1015c3SStefano Zampini           my_onz[i] += 1;
609bb1015c3SStefano Zampini         }
610bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
611bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
612bb1015c3SStefano Zampini           owner = row_ownership[index_col];
613bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
614bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
615bb1015c3SStefano Zampini           } else {
616bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
617bb1015c3SStefano Zampini           }
618bb1015c3SStefano Zampini         }
619bb1015c3SStefano Zampini       }
620bb1015c3SStefano Zampini     }
621bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
622bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
623bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
6243927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
6253927de2eSStefano Zampini       const PetscInt *cols;
626ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
6273927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
6283927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
6293927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
630ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
6313927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
6323927de2eSStefano Zampini           my_dnz[i] += 1;
6333927de2eSStefano Zampini         } else { /* offdiag block */
6343927de2eSStefano Zampini           my_onz[i] += 1;
6353927de2eSStefano Zampini         }
6363927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
637d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
6383927de2eSStefano Zampini           owner = row_ownership[index_col];
6393927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
640d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
6413927de2eSStefano Zampini           } else {
642d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
6433927de2eSStefano Zampini           }
6443927de2eSStefano Zampini         }
6453927de2eSStefano Zampini       }
6463927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
6473927de2eSStefano Zampini     }
6483927de2eSStefano Zampini   }
649ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
650ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
6517230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
652ecf5a873SStefano Zampini   }
6533927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
654ecf5a873SStefano Zampini 
655ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
6563927de2eSStefano Zampini   if (maxreduce) {
6573927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
6583927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
659bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
6603927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
6613927de2eSStefano Zampini   } else {
6623927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
6633927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
664bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
6653927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
6663927de2eSStefano Zampini   }
6673927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
6683927de2eSStefano Zampini 
6693927de2eSStefano Zampini   /* Resize preallocation if overestimated */
6703927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
6713927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
6723927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
6733927de2eSStefano Zampini   }
6743927de2eSStefano Zampini   /* set preallocation */
6753927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
6763927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
6773927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
6783927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
6793927de2eSStefano Zampini   }
6803927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
6813927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
6823927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
6833927de2eSStefano Zampini   if (issbaij) {
6843927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
6853927de2eSStefano Zampini   }
6863927de2eSStefano Zampini   PetscFunctionReturn(0);
6873927de2eSStefano Zampini }
6883927de2eSStefano Zampini 
6893927de2eSStefano Zampini #undef __FUNCT__
690b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
6917230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
692b7ce53b6SStefano Zampini {
693b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
694d9a9e74cSStefano Zampini   Mat            local_mat;
695b7ce53b6SStefano Zampini   /* info on mat */
6963cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
697b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
698686e3a49SStefano Zampini   PetscBool      isdense,issbaij,isseqaij;
6997c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
700b7ce53b6SStefano Zampini   /* values insertion */
701b7ce53b6SStefano Zampini   PetscScalar    *array;
702b7ce53b6SStefano Zampini   /* work */
703b7ce53b6SStefano Zampini   PetscErrorCode ierr;
704b7ce53b6SStefano Zampini 
705b7ce53b6SStefano Zampini   PetscFunctionBegin;
706b7ce53b6SStefano Zampini   /* get info from mat */
7077c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
7087c03b4e8SStefano Zampini   if (nsubdomains == 1) {
7097c03b4e8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
7107c03b4e8SStefano Zampini       ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&(*M));CHKERRQ(ierr);
7117c03b4e8SStefano Zampini     } else {
7127c03b4e8SStefano Zampini       ierr = MatCopy(matis->A,*M,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
7137c03b4e8SStefano Zampini     }
7147c03b4e8SStefano Zampini     PetscFunctionReturn(0);
7157c03b4e8SStefano Zampini   }
716b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
717b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
7183cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
719b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
720b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
721686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
722b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
723b7ce53b6SStefano Zampini 
724b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
725b7ce53b6SStefano Zampini     MatType     new_mat_type;
7263927de2eSStefano Zampini     PetscBool   issbaij_red;
727b7ce53b6SStefano Zampini 
728b7ce53b6SStefano Zampini     /* determining new matrix type */
729b2566f29SBarry Smith     ierr = MPIU_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
730b7ce53b6SStefano Zampini     if (issbaij_red) {
731b7ce53b6SStefano Zampini       new_mat_type = MATSBAIJ;
732b7ce53b6SStefano Zampini     } else {
733b7ce53b6SStefano Zampini       if (bs>1) {
734b7ce53b6SStefano Zampini         new_mat_type = MATBAIJ;
735b7ce53b6SStefano Zampini       } else {
736b7ce53b6SStefano Zampini         new_mat_type = MATAIJ;
737b7ce53b6SStefano Zampini       }
738b7ce53b6SStefano Zampini     }
739b7ce53b6SStefano Zampini 
7403927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
7413cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
7423927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
7433927de2eSStefano Zampini     ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr);
7443927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
745b7ce53b6SStefano Zampini   } else {
7463cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
747b7ce53b6SStefano Zampini     /* some checks */
748b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
749b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
7503cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
7516c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
7526c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
7536c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
7546c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
7556c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
756b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
757b7ce53b6SStefano Zampini   }
758d9a9e74cSStefano Zampini 
759d9a9e74cSStefano Zampini   if (issbaij) {
760d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
761d9a9e74cSStefano Zampini   } else {
762d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
763d9a9e74cSStefano Zampini     local_mat = matis->A;
764d9a9e74cSStefano Zampini   }
765686e3a49SStefano Zampini 
766b7ce53b6SStefano Zampini   /* Set values */
767ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
768b7ce53b6SStefano Zampini   if (isdense) { /* special case for dense local matrices */
769ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
770ecf5a873SStefano Zampini 
771ecf5a873SStefano Zampini     if (local_rows != local_cols) {
772ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
773ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
774ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
775ecf5a873SStefano Zampini     } else {
776ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
777ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
778ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
779ecf5a873SStefano Zampini     }
780b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
781d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
782ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
783d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
784ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
785ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
786ecf5a873SStefano Zampini     } else {
787ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
788ecf5a873SStefano Zampini     }
789686e3a49SStefano Zampini   } else if (isseqaij) {
790ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
791686e3a49SStefano Zampini     PetscBool done;
792686e3a49SStefano Zampini 
793d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
794bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
795d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
796686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
797ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
798686e3a49SStefano Zampini     }
799d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
800bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
801d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
802686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
803ecf5a873SStefano Zampini     PetscInt i;
804c0962df8SStefano Zampini 
805686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
806686e3a49SStefano Zampini       PetscInt       j;
807ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
808686e3a49SStefano Zampini 
809ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
810ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
811ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
812686e3a49SStefano Zampini     }
813b7ce53b6SStefano Zampini   }
814b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
815d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
816b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
817b7ce53b6SStefano Zampini   if (isdense) {
818b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
819b7ce53b6SStefano Zampini   }
820b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
821b7ce53b6SStefano Zampini }
822b7ce53b6SStefano Zampini 
823b7ce53b6SStefano Zampini #undef __FUNCT__
824b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
825b7ce53b6SStefano Zampini /*@
826b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
827b7ce53b6SStefano Zampini 
828b7ce53b6SStefano Zampini   Input Parameter:
829b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
830b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
831b7ce53b6SStefano Zampini 
832b7ce53b6SStefano Zampini   Output Parameter:
833b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
834b7ce53b6SStefano Zampini 
835b7ce53b6SStefano Zampini   Level: developer
836b7ce53b6SStefano Zampini 
837eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
838b7ce53b6SStefano Zampini 
839b7ce53b6SStefano Zampini .seealso: MATIS
840b7ce53b6SStefano Zampini @*/
841b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
842b7ce53b6SStefano Zampini {
843b7ce53b6SStefano Zampini   PetscErrorCode ierr;
844b7ce53b6SStefano Zampini 
845b7ce53b6SStefano Zampini   PetscFunctionBegin;
846b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
847b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
848b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
849b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
850b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
851b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
8526c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
853b7ce53b6SStefano Zampini   }
854b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
855b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
856b7ce53b6SStefano Zampini }
857b7ce53b6SStefano Zampini 
858b7ce53b6SStefano Zampini #undef __FUNCT__
859ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
860ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
861ad6194a2SStefano Zampini {
862ad6194a2SStefano Zampini   PetscErrorCode ierr;
863ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
864ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
865ad6194a2SStefano Zampini   Mat            B,localmat;
866ad6194a2SStefano Zampini 
867ad6194a2SStefano Zampini   PetscFunctionBegin;
868ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
869ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
870ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
871e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
872ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
873ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
874b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
875ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
876ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
877ad6194a2SStefano Zampini   *newmat = B;
878ad6194a2SStefano Zampini   PetscFunctionReturn(0);
879ad6194a2SStefano Zampini }
880ad6194a2SStefano Zampini 
881ad6194a2SStefano Zampini #undef __FUNCT__
88269796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
883a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
88469796d55SStefano Zampini {
88569796d55SStefano Zampini   PetscErrorCode ierr;
88669796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
88769796d55SStefano Zampini   PetscBool      local_sym;
88869796d55SStefano Zampini 
88969796d55SStefano Zampini   PetscFunctionBegin;
89069796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
891b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
89269796d55SStefano Zampini   PetscFunctionReturn(0);
89369796d55SStefano Zampini }
89469796d55SStefano Zampini 
89569796d55SStefano Zampini #undef __FUNCT__
89669796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
897a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
89869796d55SStefano Zampini {
89969796d55SStefano Zampini   PetscErrorCode ierr;
90069796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
90169796d55SStefano Zampini   PetscBool      local_sym;
90269796d55SStefano Zampini 
90369796d55SStefano Zampini   PetscFunctionBegin;
90469796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
905b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
90669796d55SStefano Zampini   PetscFunctionReturn(0);
90769796d55SStefano Zampini }
90869796d55SStefano Zampini 
90969796d55SStefano Zampini #undef __FUNCT__
910b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
911a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
912b4319ba4SBarry Smith {
913dfbe8321SBarry Smith   PetscErrorCode ierr;
914b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
915b4319ba4SBarry Smith 
916b4319ba4SBarry Smith   PetscFunctionBegin;
9176bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
918e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
919e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
9206bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
9216bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
9223fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
923a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
924a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
925a8116848SStefano Zampini   if (b->sf != b->csf) {
926a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
927a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
928a8116848SStefano Zampini   }
92928f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
93028f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
931bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
932dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
933bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
934b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
935b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
9362e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
937b4319ba4SBarry Smith   PetscFunctionReturn(0);
938b4319ba4SBarry Smith }
939b4319ba4SBarry Smith 
940b4319ba4SBarry Smith #undef __FUNCT__
941b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
942a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
943b4319ba4SBarry Smith {
944dfbe8321SBarry Smith   PetscErrorCode ierr;
945b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
946b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
947b4319ba4SBarry Smith 
948b4319ba4SBarry Smith   PetscFunctionBegin;
949b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
950e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
951e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
952b4319ba4SBarry Smith 
953b4319ba4SBarry Smith   /* multiply the local matrix */
954b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
955b4319ba4SBarry Smith 
956b4319ba4SBarry Smith   /* scatter product back into global memory */
9572dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
958e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
959e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
960b4319ba4SBarry Smith   PetscFunctionReturn(0);
961b4319ba4SBarry Smith }
962b4319ba4SBarry Smith 
963b4319ba4SBarry Smith #undef __FUNCT__
9642e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
965a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
9662e74eeadSLisandro Dalcin {
967650997f4SStefano Zampini   Vec            temp_vec;
9682e74eeadSLisandro Dalcin   PetscErrorCode ierr;
9692e74eeadSLisandro Dalcin 
9702e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
971650997f4SStefano Zampini   if (v3 != v2) {
972650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
973650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
974650997f4SStefano Zampini   } else {
975650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
976650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
977650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
978650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
979650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
980650997f4SStefano Zampini   }
9812e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
9822e74eeadSLisandro Dalcin }
9832e74eeadSLisandro Dalcin 
9842e74eeadSLisandro Dalcin #undef __FUNCT__
9852e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
986a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
9872e74eeadSLisandro Dalcin {
9882e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
9892e74eeadSLisandro Dalcin   PetscErrorCode ierr;
9902e74eeadSLisandro Dalcin 
991e176bc59SStefano Zampini   PetscFunctionBegin;
9922e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
993e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
994e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9952e74eeadSLisandro Dalcin 
9962e74eeadSLisandro Dalcin   /* multiply the local matrix */
997e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
9982e74eeadSLisandro Dalcin 
9992e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1000e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1001e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1002e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10032e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
10042e74eeadSLisandro Dalcin }
10052e74eeadSLisandro Dalcin 
10062e74eeadSLisandro Dalcin #undef __FUNCT__
10072e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
1008a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
10092e74eeadSLisandro Dalcin {
1010650997f4SStefano Zampini   Vec            temp_vec;
10112e74eeadSLisandro Dalcin   PetscErrorCode ierr;
10122e74eeadSLisandro Dalcin 
10132e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1014650997f4SStefano Zampini   if (v3 != v2) {
1015650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1016650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1017650997f4SStefano Zampini   } else {
1018650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1019650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1020650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1021650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1022650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1023650997f4SStefano Zampini   }
10242e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
10252e74eeadSLisandro Dalcin }
10262e74eeadSLisandro Dalcin 
10272e74eeadSLisandro Dalcin #undef __FUNCT__
1028b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
1029a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1030b4319ba4SBarry Smith {
1031b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1032dfbe8321SBarry Smith   PetscErrorCode ierr;
1033b4319ba4SBarry Smith   PetscViewer    sviewer;
1034b4319ba4SBarry Smith 
1035b4319ba4SBarry Smith   PetscFunctionBegin;
10363f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1037b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
10383f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
10396e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1040b4319ba4SBarry Smith   PetscFunctionReturn(0);
1041b4319ba4SBarry Smith }
1042b4319ba4SBarry Smith 
1043b4319ba4SBarry Smith #undef __FUNCT__
1044b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
1045a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1046b4319ba4SBarry Smith {
1047dfbe8321SBarry Smith   PetscErrorCode ierr;
1048e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1049b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1050b4319ba4SBarry Smith   IS             from,to;
1051e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1052b4319ba4SBarry Smith 
1053b4319ba4SBarry Smith   PetscFunctionBegin;
1054784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1055e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
10563bbff08aSStefano Zampini   /* Destroy any previous data */
105770cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
105870cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
10593fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1060e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1061e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
10621c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
106328f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
106428f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
10653bbff08aSStefano Zampini 
10663bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1067fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1068fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1069fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1070fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1071b4319ba4SBarry Smith 
1072b4319ba4SBarry Smith   /* Create the local matrix A */
1073e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1074e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1075e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1076e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1077f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1078e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1079e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1080e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1081ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1082ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1083b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1084b4319ba4SBarry Smith 
1085f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1086b4319ba4SBarry Smith     /* Create the local work vectors */
10873bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1088b4319ba4SBarry Smith 
1089e176bc59SStefano Zampini     /* setup the global to local scatters */
1090e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1091e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1092784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1093e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1094e176bc59SStefano Zampini     if (rmapping != cmapping) {
1095e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1096e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1097e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1098e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1099e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1100e176bc59SStefano Zampini     } else {
1101e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1102e176bc59SStefano Zampini       is->cctx = is->rctx;
1103e176bc59SStefano Zampini     }
11043fd1c9e7SStefano Zampini 
11053fd1c9e7SStefano Zampini     /* interface counter vector (local) */
11063fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
11073fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
11083fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11093fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11103fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11113fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11123fd1c9e7SStefano Zampini 
11133fd1c9e7SStefano Zampini     /* free workspace */
1114e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1115e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
11166bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
11176bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1118f26d0771SStefano Zampini   }
111948ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1120b4319ba4SBarry Smith   PetscFunctionReturn(0);
1121b4319ba4SBarry Smith }
1122b4319ba4SBarry Smith 
11232e74eeadSLisandro Dalcin #undef __FUNCT__
11242e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
1125a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
11262e74eeadSLisandro Dalcin {
11272e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
11282e74eeadSLisandro Dalcin   PetscErrorCode ierr;
112997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
113097563a80SStefano Zampini   PetscInt       i,zm,zn;
113197563a80SStefano Zampini #endif
1132f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
11332e74eeadSLisandro Dalcin 
11342e74eeadSLisandro Dalcin   PetscFunctionBegin;
11352e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1136f26d0771SStefano 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);
113797563a80SStefano Zampini   /* count negative indices */
113897563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
113997563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
11402e74eeadSLisandro Dalcin #endif
114197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
114297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
114397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
114497563a80SStefano Zampini   /* count negative indices (should be the same as before) */
114597563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
114697563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
114797563a80SStefano 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");
114897563a80SStefano 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");
114997563a80SStefano Zampini #endif
11502e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
11512e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
11522e74eeadSLisandro Dalcin }
11532e74eeadSLisandro Dalcin 
1154b4319ba4SBarry Smith #undef __FUNCT__
115597563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS"
1156a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
115797563a80SStefano Zampini {
115897563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
115997563a80SStefano Zampini   PetscErrorCode ierr;
116097563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
116197563a80SStefano Zampini   PetscInt       i,zm,zn;
116297563a80SStefano Zampini #endif
1163f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
116497563a80SStefano Zampini 
116597563a80SStefano Zampini   PetscFunctionBegin;
116697563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1167f26d0771SStefano 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);
116897563a80SStefano Zampini   /* count negative indices */
116997563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
117097563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
117197563a80SStefano Zampini #endif
117297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
117397563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
117497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
117597563a80SStefano Zampini   /* count negative indices (should be the same as before) */
117697563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
117797563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
117897563a80SStefano 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");
117997563a80SStefano 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");
118097563a80SStefano Zampini #endif
118197563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
118297563a80SStefano Zampini   PetscFunctionReturn(0);
118397563a80SStefano Zampini }
118497563a80SStefano Zampini 
118597563a80SStefano Zampini #undef __FUNCT__
1186b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
1187a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1188b4319ba4SBarry Smith {
1189dfbe8321SBarry Smith   PetscErrorCode ierr;
1190b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1191b4319ba4SBarry Smith 
1192b4319ba4SBarry Smith   PetscFunctionBegin;
1193b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1194b4319ba4SBarry Smith   PetscFunctionReturn(0);
1195b4319ba4SBarry Smith }
1196b4319ba4SBarry Smith 
1197b4319ba4SBarry Smith #undef __FUNCT__
1198f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
1199a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1200f0006bf2SLisandro Dalcin {
1201f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1202f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1203f0006bf2SLisandro Dalcin 
1204f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1205f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1206f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1207f0006bf2SLisandro Dalcin }
1208f0006bf2SLisandro Dalcin 
1209f0006bf2SLisandro Dalcin #undef __FUNCT__
1210f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private"
1211f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1212f0ae7da4SStefano Zampini {
1213f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1214f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1215f0ae7da4SStefano Zampini 
1216f0ae7da4SStefano Zampini   PetscFunctionBegin;
1217f0ae7da4SStefano Zampini   if (!n) {
1218f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1219f0ae7da4SStefano Zampini   } else {
1220f0ae7da4SStefano Zampini     PetscInt i;
1221f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1222f0ae7da4SStefano Zampini 
1223f0ae7da4SStefano Zampini     if (columns) {
1224f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1225f0ae7da4SStefano Zampini     } else {
1226f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1227f0ae7da4SStefano Zampini     }
1228f0ae7da4SStefano Zampini     if (diag != 0.) {
1229f0ae7da4SStefano Zampini       const PetscScalar *array;
1230f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1231f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1232f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1233f0ae7da4SStefano Zampini       }
1234f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1235f0ae7da4SStefano Zampini     }
1236f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1237f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1238f0ae7da4SStefano Zampini   }
1239f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1240f0ae7da4SStefano Zampini }
1241f0ae7da4SStefano Zampini 
1242f0ae7da4SStefano Zampini #undef __FUNCT__
1243f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS"
1244f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
12452e74eeadSLisandro Dalcin {
12466e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
12476e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
12486e520ac8SStefano Zampini   PetscInt       *lrows;
12492e74eeadSLisandro Dalcin   PetscErrorCode ierr;
12502e74eeadSLisandro Dalcin 
12512e74eeadSLisandro Dalcin   PetscFunctionBegin;
1252f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1253f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1254f0ae7da4SStefano Zampini     PetscBool cong;
1255f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1256f0ae7da4SStefano Zampini     if (!cong && columns) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Columns can be zeroed if and only if A->rmap and A->cmap are congruent for MATIS");
1257f0ae7da4SStefano Zampini     if (!cong && diag != 0.) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Nonzero diagonal value supported if and only if A->rmap and A->cmap are congruent for MATIS");
1258f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1259f0ae7da4SStefano Zampini   }
1260f0ae7da4SStefano Zampini #endif
12616e520ac8SStefano Zampini   /* get locally owned rows */
1262f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
12636e520ac8SStefano Zampini   /* fix right hand side if needed */
12646e520ac8SStefano Zampini   if (x && b) {
12656e520ac8SStefano Zampini     const PetscScalar *xx;
12666e520ac8SStefano Zampini     PetscScalar       *bb;
12676e520ac8SStefano Zampini 
12686e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
12696e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
12706e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
12716e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
12726e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
12732e74eeadSLisandro Dalcin   }
12746e520ac8SStefano Zampini   /* get rows associated to the local matrices */
12756e520ac8SStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
12766e520ac8SStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
12776e520ac8SStefano Zampini   }
12786e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
12796e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
12806e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
12816e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
12826e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
12836e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
12846e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
12856e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
12866e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1287f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
12886e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
12892e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
12902e74eeadSLisandro Dalcin }
12912e74eeadSLisandro Dalcin 
12922e74eeadSLisandro Dalcin #undef __FUNCT__
1293f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS"
1294f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1295b4319ba4SBarry Smith {
1296dfbe8321SBarry Smith   PetscErrorCode ierr;
1297b4319ba4SBarry Smith 
1298b4319ba4SBarry Smith   PetscFunctionBegin;
1299f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1300f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1301f0ae7da4SStefano Zampini }
13022205254eSKarl Rupp 
1303f0ae7da4SStefano Zampini #undef __FUNCT__
1304f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS"
1305f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1306f0ae7da4SStefano Zampini {
1307f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1308f0ae7da4SStefano Zampini 
1309f0ae7da4SStefano Zampini   PetscFunctionBegin;
1310f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1311b4319ba4SBarry Smith   PetscFunctionReturn(0);
1312b4319ba4SBarry Smith }
1313b4319ba4SBarry Smith 
1314b4319ba4SBarry Smith #undef __FUNCT__
1315b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
1316a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1317b4319ba4SBarry Smith {
1318b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1319dfbe8321SBarry Smith   PetscErrorCode ierr;
1320b4319ba4SBarry Smith 
1321b4319ba4SBarry Smith   PetscFunctionBegin;
1322b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1323b4319ba4SBarry Smith   PetscFunctionReturn(0);
1324b4319ba4SBarry Smith }
1325b4319ba4SBarry Smith 
1326b4319ba4SBarry Smith #undef __FUNCT__
1327b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
1328a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1329b4319ba4SBarry Smith {
1330b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1331dfbe8321SBarry Smith   PetscErrorCode ierr;
1332b4319ba4SBarry Smith 
1333b4319ba4SBarry Smith   PetscFunctionBegin;
1334b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1335b4319ba4SBarry Smith   PetscFunctionReturn(0);
1336b4319ba4SBarry Smith }
1337b4319ba4SBarry Smith 
1338b4319ba4SBarry Smith #undef __FUNCT__
1339b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
1340a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1341b4319ba4SBarry Smith {
1342b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1343b4319ba4SBarry Smith 
1344b4319ba4SBarry Smith   PetscFunctionBegin;
1345b4319ba4SBarry Smith   *local = is->A;
1346b4319ba4SBarry Smith   PetscFunctionReturn(0);
1347b4319ba4SBarry Smith }
1348b4319ba4SBarry Smith 
1349b4319ba4SBarry Smith #undef __FUNCT__
1350b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
1351b4319ba4SBarry Smith /*@
1352b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1353b4319ba4SBarry Smith 
1354b4319ba4SBarry Smith   Input Parameter:
1355b4319ba4SBarry Smith .  mat - the matrix
1356b4319ba4SBarry Smith 
1357b4319ba4SBarry Smith   Output Parameter:
1358eb82efa4SStefano Zampini .  local - the local matrix
1359b4319ba4SBarry Smith 
1360b4319ba4SBarry Smith   Level: advanced
1361b4319ba4SBarry Smith 
1362b4319ba4SBarry Smith   Notes:
1363b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1364b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1365b4319ba4SBarry Smith   of the MatSetValues() operation.
1366b4319ba4SBarry Smith 
1367b4319ba4SBarry Smith .seealso: MATIS
1368b4319ba4SBarry Smith @*/
13697087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1370b4319ba4SBarry Smith {
13714ac538c5SBarry Smith   PetscErrorCode ierr;
1372b4319ba4SBarry Smith 
1373b4319ba4SBarry Smith   PetscFunctionBegin;
13740700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1375b4319ba4SBarry Smith   PetscValidPointer(local,2);
13764ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1377b4319ba4SBarry Smith   PetscFunctionReturn(0);
1378b4319ba4SBarry Smith }
1379b4319ba4SBarry Smith 
13803b03a366Sstefano_zampini #undef __FUNCT__
13813b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
1382a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
13833b03a366Sstefano_zampini {
13843b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
13853b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
13863b03a366Sstefano_zampini   PetscErrorCode ierr;
13873b03a366Sstefano_zampini 
13883b03a366Sstefano_zampini   PetscFunctionBegin;
13894e4c7dbeSStefano Zampini   if (is->A) {
13903b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
13913b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1392f0ae7da4SStefano Zampini     if (orows != nrows || ocols != ncols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %Dx%D (you passed a %Dx%D matrix)",orows,ocols,nrows,ncols);
13934e4c7dbeSStefano Zampini   }
13943b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
13953b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
13963b03a366Sstefano_zampini   is->A = local;
13973b03a366Sstefano_zampini   PetscFunctionReturn(0);
13983b03a366Sstefano_zampini }
13993b03a366Sstefano_zampini 
14003b03a366Sstefano_zampini #undef __FUNCT__
14013b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
14023b03a366Sstefano_zampini /*@
1403eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
14043b03a366Sstefano_zampini 
14053b03a366Sstefano_zampini   Input Parameter:
14063b03a366Sstefano_zampini .  mat - the matrix
1407eb82efa4SStefano Zampini .  local - the local matrix
14083b03a366Sstefano_zampini 
14093b03a366Sstefano_zampini   Output Parameter:
14103b03a366Sstefano_zampini 
14113b03a366Sstefano_zampini   Level: advanced
14123b03a366Sstefano_zampini 
14133b03a366Sstefano_zampini   Notes:
14143b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
14153b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
14163b03a366Sstefano_zampini 
14173b03a366Sstefano_zampini .seealso: MATIS
14183b03a366Sstefano_zampini @*/
14193b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
14203b03a366Sstefano_zampini {
14213b03a366Sstefano_zampini   PetscErrorCode ierr;
14223b03a366Sstefano_zampini 
14233b03a366Sstefano_zampini   PetscFunctionBegin;
14243b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1425b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
14263b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
14273b03a366Sstefano_zampini   PetscFunctionReturn(0);
14283b03a366Sstefano_zampini }
14293b03a366Sstefano_zampini 
14306726f965SBarry Smith #undef __FUNCT__
14316726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
1432a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
14336726f965SBarry Smith {
14346726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
14356726f965SBarry Smith   PetscErrorCode ierr;
14366726f965SBarry Smith 
14376726f965SBarry Smith   PetscFunctionBegin;
14386726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
14396726f965SBarry Smith   PetscFunctionReturn(0);
14406726f965SBarry Smith }
14416726f965SBarry Smith 
14426726f965SBarry Smith #undef __FUNCT__
14432e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
1444a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
14452e74eeadSLisandro Dalcin {
14462e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
14472e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14482e74eeadSLisandro Dalcin 
14492e74eeadSLisandro Dalcin   PetscFunctionBegin;
14502e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
14512e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14522e74eeadSLisandro Dalcin }
14532e74eeadSLisandro Dalcin 
14542e74eeadSLisandro Dalcin #undef __FUNCT__
14552e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
1456a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
14572e74eeadSLisandro Dalcin {
14582e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
14592e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14602e74eeadSLisandro Dalcin 
14612e74eeadSLisandro Dalcin   PetscFunctionBegin;
14622e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
1463e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
14642e74eeadSLisandro Dalcin 
14652e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
14662e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
1467e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1468e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14692e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14702e74eeadSLisandro Dalcin }
14712e74eeadSLisandro Dalcin 
14722e74eeadSLisandro Dalcin #undef __FUNCT__
14736726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
1474a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
14756726f965SBarry Smith {
14766726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
14776726f965SBarry Smith   PetscErrorCode ierr;
14786726f965SBarry Smith 
14796726f965SBarry Smith   PetscFunctionBegin;
14804e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
14816726f965SBarry Smith   PetscFunctionReturn(0);
14826726f965SBarry Smith }
14836726f965SBarry Smith 
1484284134d9SBarry Smith #undef __FUNCT__
1485f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS"
1486f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
1487f26d0771SStefano Zampini {
1488f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
1489f26d0771SStefano Zampini   Mat_IS         *x;
1490f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1491f26d0771SStefano Zampini   PetscBool      ismatis;
1492f26d0771SStefano Zampini #endif
1493f26d0771SStefano Zampini   PetscErrorCode ierr;
1494f26d0771SStefano Zampini 
1495f26d0771SStefano Zampini   PetscFunctionBegin;
1496f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1497f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
1498f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
1499f26d0771SStefano Zampini #endif
1500f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
1501f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
1502f26d0771SStefano Zampini   PetscFunctionReturn(0);
1503f26d0771SStefano Zampini }
1504f26d0771SStefano Zampini 
1505f26d0771SStefano Zampini #undef __FUNCT__
1506f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS"
1507f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
1508f26d0771SStefano Zampini {
1509f26d0771SStefano Zampini   Mat                    lA;
1510f26d0771SStefano Zampini   Mat_IS                 *matis;
1511f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
1512f26d0771SStefano Zampini   IS                     is;
1513f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
1514f26d0771SStefano Zampini   PetscInt               nrg;
1515f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
1516f26d0771SStefano Zampini   PetscErrorCode         ierr;
1517f26d0771SStefano Zampini 
1518f26d0771SStefano Zampini   PetscFunctionBegin;
1519f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1520f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
1521f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
1522f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
1523f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1524f0ae7da4SStefano 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",i,rl[i],nrg);
1525f26d0771SStefano Zampini #endif
1526f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
1527f26d0771SStefano Zampini   /* map from [0,nrl) to row */
1528f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
1529f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1530f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
1531f26d0771SStefano Zampini #else
1532f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
1533f26d0771SStefano Zampini #endif
1534f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
1535f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1536f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1537f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1538f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
1539f26d0771SStefano Zampini   /* compute new l2g map for columns */
1540f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
1541f26d0771SStefano Zampini     const PetscInt *cg,*cl;
1542f26d0771SStefano Zampini     PetscInt       ncg;
1543f26d0771SStefano Zampini     PetscInt       ncl;
1544f26d0771SStefano Zampini 
1545f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1546f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
1547f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
1548f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
1549f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1550f0ae7da4SStefano 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",i,cl[i],ncg);
1551f26d0771SStefano Zampini #endif
1552f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
1553f26d0771SStefano Zampini     /* map from [0,ncl) to col */
1554f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
1555f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1556f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
1557f26d0771SStefano Zampini #else
1558f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
1559f26d0771SStefano Zampini #endif
1560f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
1561f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1562f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1563f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1564f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1565f26d0771SStefano Zampini   } else {
1566f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
1567f26d0771SStefano Zampini     cl2g = rl2g;
1568f26d0771SStefano Zampini   }
1569f26d0771SStefano Zampini   /* create the MATIS submatrix */
1570f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
1571f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
1572f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1573f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
1574b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
1575f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
1576f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
1577f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1578f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
1579f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
1580f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1581f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1582f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1583f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1584f26d0771SStefano Zampini   /* remove unsupported ops */
1585f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1586f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
1587f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
1588f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
1589f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
1590f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
1591f26d0771SStefano Zampini   PetscFunctionReturn(0);
1592f26d0771SStefano Zampini }
1593f26d0771SStefano Zampini 
1594f26d0771SStefano Zampini #undef __FUNCT__
1595284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
1596284134d9SBarry Smith /*@
15973c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
1598284134d9SBarry Smith        process but not across processes.
1599284134d9SBarry Smith 
1600284134d9SBarry Smith    Input Parameters:
1601284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
1602e176bc59SStefano Zampini .     bs      - block size of the matrix
1603df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
1604e176bc59SStefano Zampini .     rmap    - local to global map for rows
1605e176bc59SStefano Zampini -     cmap    - local to global map for cols
1606284134d9SBarry Smith 
1607284134d9SBarry Smith    Output Parameter:
1608284134d9SBarry Smith .    A - the resulting matrix
1609284134d9SBarry Smith 
16108e6c10adSSatish Balay    Level: advanced
16118e6c10adSSatish Balay 
16123c212e90SHong Zhang    Notes: See MATIS for more details.
16136fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
16146fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
16153c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
1616284134d9SBarry Smith 
1617284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
1618284134d9SBarry Smith @*/
1619e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
1620284134d9SBarry Smith {
1621284134d9SBarry Smith   PetscErrorCode ierr;
1622284134d9SBarry Smith 
1623284134d9SBarry Smith   PetscFunctionBegin;
16246fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
1625284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
16266fdf41d1SStefano Zampini   if (bs > 0) {
1627d3ee2243SStefano Zampini     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
16286fdf41d1SStefano Zampini   }
1629284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
1630284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
1631e176bc59SStefano Zampini   if (rmap && cmap) {
1632e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
1633e176bc59SStefano Zampini   } else if (!rmap) {
1634e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
1635e176bc59SStefano Zampini   } else {
1636e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
1637e176bc59SStefano Zampini   }
1638284134d9SBarry Smith   PetscFunctionReturn(0);
1639284134d9SBarry Smith }
1640284134d9SBarry Smith 
1641b4319ba4SBarry Smith /*MC
1642f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
1643b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
1644b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
1645b4319ba4SBarry Smith    product is handled "implicitly".
1646b4319ba4SBarry Smith 
1647b4319ba4SBarry Smith    Operations Provided:
16486726f965SBarry Smith +  MatMult()
16492e74eeadSLisandro Dalcin .  MatMultAdd()
16502e74eeadSLisandro Dalcin .  MatMultTranspose()
16512e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
16526726f965SBarry Smith .  MatZeroEntries()
16536726f965SBarry Smith .  MatSetOption()
16542e74eeadSLisandro Dalcin .  MatZeroRows()
16552e74eeadSLisandro Dalcin .  MatSetValues()
165697563a80SStefano Zampini .  MatSetValuesBlocked()
16576726f965SBarry Smith .  MatSetValuesLocal()
165897563a80SStefano Zampini .  MatSetValuesBlockedLocal()
16592e74eeadSLisandro Dalcin .  MatScale()
16602e74eeadSLisandro Dalcin .  MatGetDiagonal()
16612b404112SStefano Zampini .  MatMissingDiagonal()
16622b404112SStefano Zampini .  MatDuplicate()
16632b404112SStefano Zampini .  MatCopy()
1664f26d0771SStefano Zampini .  MatAXPY()
1665f26d0771SStefano Zampini .  MatGetSubMatrix()
1666f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
1667d7f69cd0SStefano Zampini .  MatTranspose()
16686726f965SBarry Smith -  MatSetLocalToGlobalMapping()
1669b4319ba4SBarry Smith 
1670b4319ba4SBarry Smith    Options Database Keys:
1671b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
1672b4319ba4SBarry Smith 
1673b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
1674b4319ba4SBarry Smith 
1675b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
1676b4319ba4SBarry Smith 
1677b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
1678eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
1679b4319ba4SBarry Smith 
1680b4319ba4SBarry Smith   Level: advanced
1681b4319ba4SBarry Smith 
1682f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
1683b4319ba4SBarry Smith 
1684b4319ba4SBarry Smith M*/
1685b4319ba4SBarry Smith 
1686b4319ba4SBarry Smith #undef __FUNCT__
1687b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
16888cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
1689b4319ba4SBarry Smith {
1690dfbe8321SBarry Smith   PetscErrorCode ierr;
1691b4319ba4SBarry Smith   Mat_IS         *b;
1692b4319ba4SBarry Smith 
1693b4319ba4SBarry Smith   PetscFunctionBegin;
1694b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
1695b4319ba4SBarry Smith   A->data = (void*)b;
1696b4319ba4SBarry Smith 
1697e176bc59SStefano Zampini   /* matrix ops */
1698e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1699b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
17002e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
17012e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
17022e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
1703b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
1704b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
17052e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
170698921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
1707b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
1708f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
17092e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
1710f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
1711b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
1712b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
1713b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
17146726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
17152e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
17162e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
17176726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
171869796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
171969796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
1720ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
17216bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
17222b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
1723659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
1724a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
1725f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
17263fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
17273fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
1728d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
1729b4319ba4SBarry Smith 
1730b7ce53b6SStefano Zampini   /* special MATIS functions */
1731bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
1732bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
1733b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
17342e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
173517667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
1736b4319ba4SBarry Smith   PetscFunctionReturn(0);
1737b4319ba4SBarry Smith }
1738