xref: /petsc/src/mat/impls/is/matis.c (revision 7fa8f2d3c229ab24d2648dd75b628cc252fb1e95)
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__
17*7fa8f2d3SStefano Zampini #define __FUNCT__ "MatGetInfo_IS"
18*7fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
19*7fa8f2d3SStefano Zampini {
20*7fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
21*7fa8f2d3SStefano Zampini   MatInfo        info;
22*7fa8f2d3SStefano Zampini   PetscReal      isend[5],irecv[5];
23*7fa8f2d3SStefano Zampini   PetscInt       bs;
24*7fa8f2d3SStefano Zampini   PetscErrorCode ierr;
25*7fa8f2d3SStefano Zampini 
26*7fa8f2d3SStefano Zampini   PetscFunctionBegin;
27*7fa8f2d3SStefano Zampini   ierr     = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
28*7fa8f2d3SStefano Zampini   ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
29*7fa8f2d3SStefano Zampini   isend[0] = info.nz_used;
30*7fa8f2d3SStefano Zampini   isend[1] = info.nz_allocated;
31*7fa8f2d3SStefano Zampini   isend[2] = info.nz_unneeded;
32*7fa8f2d3SStefano Zampini   isend[3] = info.memory;
33*7fa8f2d3SStefano Zampini   isend[4] = info.mallocs;
34*7fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
35*7fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
36*7fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
37*7fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
38*7fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
39*7fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
40*7fa8f2d3SStefano Zampini     ginfo->assemblies   = matis->A->num_ass;
41*7fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
42*7fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
43*7fa8f2d3SStefano Zampini 
44*7fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
45*7fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
46*7fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
47*7fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
48*7fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
49*7fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
50*7fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
51*7fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
52*7fa8f2d3SStefano Zampini 
53*7fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
54*7fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
55*7fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
56*7fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
57*7fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
58*7fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
59*7fa8f2d3SStefano Zampini   }
60*7fa8f2d3SStefano Zampini   ginfo->block_size        = bs;
61*7fa8f2d3SStefano Zampini   ginfo->fill_ratio_given  = 0;
62*7fa8f2d3SStefano Zampini   ginfo->fill_ratio_needed = 0;
63*7fa8f2d3SStefano Zampini   ginfo->factor_mallocs    = 0;
64*7fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
65*7fa8f2d3SStefano Zampini }
66*7fa8f2d3SStefano Zampini 
67*7fa8f2d3SStefano Zampini #undef __FUNCT__
68d7f69cd0SStefano Zampini #define __FUNCT__ "MatTranspose_IS"
69d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
70d7f69cd0SStefano Zampini {
71d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
72d7f69cd0SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
73d7f69cd0SStefano Zampini   PetscBool              notset = PETSC_FALSE,cong = PETSC_TRUE;
74d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
75d7f69cd0SStefano Zampini 
76d7f69cd0SStefano Zampini   PetscFunctionBegin;
77d7f69cd0SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
78d7f69cd0SStefano Zampini     PetscBool rcong,ccong;
79d7f69cd0SStefano Zampini 
80d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr);
81d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr);
82fa520230SStefano Zampini     cong = (PetscBool)(rcong || ccong);
83d7f69cd0SStefano Zampini   }
84d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) {
85d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
86d7f69cd0SStefano Zampini   } else {
87d7f69cd0SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,&notset);CHKERRQ(ierr);
88d7f69cd0SStefano Zampini     C = *B;
89d7f69cd0SStefano Zampini   }
90d7f69cd0SStefano Zampini 
91d7f69cd0SStefano Zampini   if (!notset) {
92d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
93d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
94d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
95d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
96d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
97d7f69cd0SStefano Zampini   }
98d7f69cd0SStefano Zampini 
99d7f69cd0SStefano Zampini   /* perform local transposition */
100d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
101d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
102d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
103d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
104d7f69cd0SStefano Zampini 
105d7f69cd0SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
106d7f69cd0SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
107d7f69cd0SStefano Zampini 
108d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
109d7f69cd0SStefano Zampini     if (!cong) {
110d7f69cd0SStefano Zampini       ierr = MatDestroy(B);CHKERRQ(ierr);
111d7f69cd0SStefano Zampini     }
112d7f69cd0SStefano Zampini     *B = C;
113d7f69cd0SStefano Zampini   } else {
114d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
115d7f69cd0SStefano Zampini   }
116d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
117d7f69cd0SStefano Zampini }
118d7f69cd0SStefano Zampini 
119d7f69cd0SStefano Zampini #undef __FUNCT__
1203fd1c9e7SStefano Zampini #define __FUNCT__ "MatDiagonalSet_IS"
1213fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
1223fd1c9e7SStefano Zampini {
1233fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1243fd1c9e7SStefano Zampini   PetscErrorCode ierr;
1253fd1c9e7SStefano Zampini 
1263fd1c9e7SStefano Zampini   PetscFunctionBegin;
1273fd1c9e7SStefano Zampini   if (!D) { /* this code branch is used by MatShift_IS */
1283fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
1293fd1c9e7SStefano Zampini   } else {
1303fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1313fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1323fd1c9e7SStefano Zampini   }
1333fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
1343fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
1353fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
1363fd1c9e7SStefano Zampini }
1373fd1c9e7SStefano Zampini 
1383fd1c9e7SStefano Zampini #undef __FUNCT__
1393fd1c9e7SStefano Zampini #define __FUNCT__ "MatShift_IS"
1403fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
1413fd1c9e7SStefano Zampini {
1423fd1c9e7SStefano Zampini   PetscErrorCode ierr;
1433fd1c9e7SStefano Zampini 
1443fd1c9e7SStefano Zampini   PetscFunctionBegin;
1453fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
1463fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
1473fd1c9e7SStefano Zampini }
1483fd1c9e7SStefano Zampini 
1493fd1c9e7SStefano Zampini #undef __FUNCT__
150f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS"
151f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
152f26d0771SStefano Zampini {
153f26d0771SStefano Zampini   PetscErrorCode ierr;
154f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
155f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
156f26d0771SStefano Zampini 
157f26d0771SStefano Zampini   PetscFunctionBegin;
158f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
159f26d0771SStefano 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);
160f26d0771SStefano Zampini #endif
161f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
162f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
163f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
164f26d0771SStefano Zampini   PetscFunctionReturn(0);
165f26d0771SStefano Zampini }
166f26d0771SStefano Zampini 
167f26d0771SStefano Zampini #undef __FUNCT__
168f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS"
169f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
170f26d0771SStefano Zampini {
171f26d0771SStefano Zampini   PetscErrorCode ierr;
172f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
173f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
174f26d0771SStefano Zampini 
175f26d0771SStefano Zampini   PetscFunctionBegin;
176f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
177f26d0771SStefano 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);
178f26d0771SStefano Zampini #endif
179f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
180f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
181f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
182f26d0771SStefano Zampini   PetscFunctionReturn(0);
183f26d0771SStefano Zampini }
184f26d0771SStefano Zampini 
185f26d0771SStefano Zampini #undef __FUNCT__
186a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private"
187f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
188a8116848SStefano Zampini {
189a8116848SStefano Zampini   PetscInt      *owners = map->range;
190a8116848SStefano Zampini   PetscInt       n      = map->n;
191a8116848SStefano Zampini   PetscSF        sf;
192a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
193a8116848SStefano Zampini   PetscSFNode   *ridxs;
194a8116848SStefano Zampini   PetscMPIInt    rank;
195a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
196a8116848SStefano Zampini   PetscErrorCode ierr;
197a8116848SStefano Zampini 
198a8116848SStefano Zampini   PetscFunctionBegin;
199a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
200a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
201a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
202a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
203a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
204a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
205a8116848SStefano Zampini     const PetscInt idx = idxs[r];
206a8116848SStefano 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);
207a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
208a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
209a8116848SStefano Zampini     }
210a8116848SStefano Zampini     ridxs[r].rank = p;
211a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
212a8116848SStefano Zampini   }
213a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
214a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
215a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
216a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
217f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
218a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
219f0ae7da4SStefano Zampini 
220f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
221a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
222a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
223a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
224a8116848SStefano Zampini     start -= cum;
225a8116848SStefano Zampini     cum = 0;
226a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
227a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
228a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
229a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
230a8116848SStefano Zampini   }
231a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
232a8116848SStefano Zampini   /* Compress and put in indices */
233a8116848SStefano Zampini   for (r = 0; r < n; ++r)
234a8116848SStefano Zampini     if (lidxs[r] >= 0) {
235a8116848SStefano Zampini       if (work) work[len] = work[r];
236a8116848SStefano Zampini       lidxs[len++] = r;
237a8116848SStefano Zampini     }
238a8116848SStefano Zampini   if (on) *on = len;
239a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
240a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
241a8116848SStefano Zampini   PetscFunctionReturn(0);
242a8116848SStefano Zampini }
243a8116848SStefano Zampini 
244a8116848SStefano Zampini #undef __FUNCT__
245a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS"
246a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
247a8116848SStefano Zampini {
248a8116848SStefano Zampini   Mat               locmat,newlocmat;
249a8116848SStefano Zampini   Mat_IS            *newmatis;
250a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
251a8116848SStefano Zampini   Vec               rtest,ltest;
252a8116848SStefano Zampini   const PetscScalar *array;
253a8116848SStefano Zampini #endif
254a8116848SStefano Zampini   const PetscInt    *idxs;
255a8116848SStefano Zampini   PetscInt          i,m,n;
256a8116848SStefano Zampini   PetscErrorCode    ierr;
257a8116848SStefano Zampini 
258a8116848SStefano Zampini   PetscFunctionBegin;
259a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
260a8116848SStefano Zampini     PetscBool ismatis;
261a8116848SStefano Zampini 
262a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
263a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
264a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
265a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
266a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
267a8116848SStefano Zampini   }
268a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
269a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
270a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
271a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
272a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
273a8116848SStefano Zampini   for (i=0;i<n;i++) {
274a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
275a8116848SStefano Zampini   }
276a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
277a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
278a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
279a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
280a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
281fd479f66SMatthew 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]));
282a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
283a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
284a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
285a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
286a8116848SStefano Zampini   for (i=0;i<n;i++) {
287a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
288a8116848SStefano Zampini   }
289a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
290a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
291a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
292a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
293a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
294fd479f66SMatthew 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]));
295a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
296a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
297a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
298a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
299a8116848SStefano Zampini #endif
300a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
301a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
302a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
303a8116848SStefano Zampini     IS                     is;
304a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
3056dd40735SStefano Zampini     PetscInt               ll,newloc;
306a8116848SStefano Zampini     MPI_Comm               comm;
307a8116848SStefano Zampini 
308a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
309a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
310a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
311a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
312a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
313a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
314a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
315a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
316f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
317a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
318a8116848SStefano Zampini     if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
319a8116848SStefano Zampini       ierr = MatISComputeSF_Private(mat);CHKERRQ(ierr);
320a8116848SStefano Zampini     }
321a8116848SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
322a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
323a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
324a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
325a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
326a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
327a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
328a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
329a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
330a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++)
331a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
332a8116848SStefano Zampini         lidxs[newloc] = i;
333a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
334a8116848SStefano Zampini       }
335a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
336a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
337a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
338a8116848SStefano Zampini     /* local is to extract local submatrix */
339a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
340a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
341a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
342a8116848SStefano Zampini       PetscBool cong;
343a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
344a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
345a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
346a8116848SStefano Zampini     }
347a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
348a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
349a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
350a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
351a8116848SStefano Zampini     } else {
352a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
353a8116848SStefano Zampini 
354a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
355a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
356f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
357a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
358a8116848SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
359a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
360a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
361a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
362a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
363a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
364a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
365a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
366a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
367a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++)
368a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
369a8116848SStefano Zampini           lidxs[newloc] = i;
370a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
371a8116848SStefano Zampini         }
372a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
373a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
374a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
375a8116848SStefano Zampini       /* local is to extract local submatrix */
376a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
377a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
378a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
379a8116848SStefano Zampini     }
380a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
381a8116848SStefano Zampini   } else {
382a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
383a8116848SStefano Zampini   }
384a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
385a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
386a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
387a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
388a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
389a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
390a8116848SStefano Zampini   }
391a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
392a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
393a8116848SStefano Zampini   PetscFunctionReturn(0);
394a8116848SStefano Zampini }
395a8116848SStefano Zampini 
396a8116848SStefano Zampini #undef __FUNCT__
3972b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS"
398a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
3992b404112SStefano Zampini {
4002b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
4012b404112SStefano Zampini   PetscBool      ismatis;
4022b404112SStefano Zampini   PetscErrorCode ierr;
4032b404112SStefano Zampini 
4042b404112SStefano Zampini   PetscFunctionBegin;
4052b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
4062b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
4072b404112SStefano Zampini   b = (Mat_IS*)B->data;
4082b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
4092b404112SStefano Zampini   PetscFunctionReturn(0);
4102b404112SStefano Zampini }
4112b404112SStefano Zampini 
4122b404112SStefano Zampini #undef __FUNCT__
4136bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS"
414a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
4156bd84002SStefano Zampini {
416527b2640SStefano Zampini   Vec               v;
417527b2640SStefano Zampini   const PetscScalar *array;
418527b2640SStefano Zampini   PetscInt          i,n;
4196bd84002SStefano Zampini   PetscErrorCode    ierr;
4206bd84002SStefano Zampini 
4216bd84002SStefano Zampini   PetscFunctionBegin;
422527b2640SStefano Zampini   *missing = PETSC_FALSE;
423527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
424527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
425527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
426527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
427527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
428527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
429527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
430527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
431527b2640SStefano Zampini   if (d) {
432527b2640SStefano Zampini     *d = -1;
433527b2640SStefano Zampini     if (*missing) {
434527b2640SStefano Zampini       PetscInt rstart;
435527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
436527b2640SStefano Zampini       *d = i+rstart;
437527b2640SStefano Zampini     }
438527b2640SStefano Zampini   }
4396bd84002SStefano Zampini   PetscFunctionReturn(0);
4406bd84002SStefano Zampini }
4416bd84002SStefano Zampini 
4426bd84002SStefano Zampini #undef __FUNCT__
44328f4e0baSStefano Zampini #define __FUNCT__ "MatISComputeSF_Private"
444a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat B)
44528f4e0baSStefano Zampini {
44628f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
44728f4e0baSStefano Zampini   const PetscInt *gidxs;
44828f4e0baSStefano Zampini   PetscErrorCode ierr;
44928f4e0baSStefano Zampini 
45028f4e0baSStefano Zampini   PetscFunctionBegin;
45128f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,&matis->sf_nleaves,NULL);CHKERRQ(ierr);
45228f4e0baSStefano Zampini   ierr = MatGetLocalSize(B,&matis->sf_nroots,NULL);CHKERRQ(ierr);
45328f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
4543bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
45528f4e0baSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,matis->sf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
4563bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
45728f4e0baSStefano Zampini   ierr = PetscMalloc2(matis->sf_nroots,&matis->sf_rootdata,matis->sf_nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
458a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
459a8116848SStefano Zampini     ierr = MatGetSize(matis->A,NULL,&matis->csf_nleaves);CHKERRQ(ierr);
460a8116848SStefano Zampini     ierr = MatGetLocalSize(B,NULL,&matis->csf_nroots);CHKERRQ(ierr);
461a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
462a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
463a8116848SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,matis->csf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
464a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
465a8116848SStefano Zampini     ierr = PetscMalloc2(matis->csf_nroots,&matis->csf_rootdata,matis->csf_nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
466a8116848SStefano Zampini   } else {
467a8116848SStefano Zampini     matis->csf = matis->sf;
468a8116848SStefano Zampini     matis->csf_nleaves = matis->sf_nleaves;
469a8116848SStefano Zampini     matis->csf_nroots = matis->sf_nroots;
470a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
471a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
472a8116848SStefano Zampini   }
47328f4e0baSStefano Zampini   PetscFunctionReturn(0);
47428f4e0baSStefano Zampini }
4752e1947a5SStefano Zampini 
4762e1947a5SStefano Zampini #undef __FUNCT__
4772e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
478eb82efa4SStefano Zampini /*@
479a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
480a88811baSStefano Zampini 
481a88811baSStefano Zampini    Collective on MPI_Comm
482a88811baSStefano Zampini 
483a88811baSStefano Zampini    Input Parameters:
484a88811baSStefano Zampini +  B - the matrix
485a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
486a88811baSStefano Zampini            (same value is used for all local rows)
487a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
488a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
489a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
490a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
491a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
492a88811baSStefano Zampini            the diagonal entry even if it is zero.
493a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
494a88811baSStefano Zampini            submatrix (same value is used for all local rows).
495a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
496a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
497a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
498a88811baSStefano Zampini            structure. The size of this array is equal to the number
499a88811baSStefano Zampini            of local rows, i.e 'm'.
500a88811baSStefano Zampini 
501a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
502a88811baSStefano Zampini 
503a88811baSStefano Zampini    Level: intermediate
504a88811baSStefano Zampini 
505a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
506a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
507a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
508a88811baSStefano Zampini 
509a88811baSStefano Zampini .keywords: matrix
510a88811baSStefano Zampini 
5113c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
512a88811baSStefano Zampini @*/
5132e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
5142e1947a5SStefano Zampini {
5152e1947a5SStefano Zampini   PetscErrorCode ierr;
5162e1947a5SStefano Zampini 
5172e1947a5SStefano Zampini   PetscFunctionBegin;
5182e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
5192e1947a5SStefano Zampini   PetscValidType(B,1);
5202e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
5212e1947a5SStefano Zampini   PetscFunctionReturn(0);
5222e1947a5SStefano Zampini }
5232e1947a5SStefano Zampini 
5242e1947a5SStefano Zampini #undef __FUNCT__
5252e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
5267230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
5272e1947a5SStefano Zampini {
5282e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
52928f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
5302e1947a5SStefano Zampini   PetscErrorCode ierr;
5312e1947a5SStefano Zampini 
5322e1947a5SStefano Zampini   PetscFunctionBegin;
5336c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
53428f4e0baSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
53528f4e0baSStefano Zampini     ierr = MatISComputeSF_Private(B);CHKERRQ(ierr);
53628f4e0baSStefano Zampini   }
5372e1947a5SStefano Zampini   if (!d_nnz) {
53828f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nz;
5392e1947a5SStefano Zampini   } else {
54028f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
5412e1947a5SStefano Zampini   }
5422e1947a5SStefano Zampini   if (!o_nnz) {
54328f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nz;
5442e1947a5SStefano Zampini   } else {
54528f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
5462e1947a5SStefano Zampini   }
54728f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
54828f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
54928f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
55028f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
55128f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves;i++) {
55228f4e0baSStefano Zampini     matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
5532e1947a5SStefano Zampini   }
55428f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
55528f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
55628f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
5572e1947a5SStefano Zampini   }
55828f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
55928f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
56028f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
5612e1947a5SStefano Zampini   }
56228f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
5632e1947a5SStefano Zampini   PetscFunctionReturn(0);
5642e1947a5SStefano Zampini }
565b4319ba4SBarry Smith 
566b4319ba4SBarry Smith #undef __FUNCT__
5673927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
5683927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
5693927de2eSStefano Zampini {
5703927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
5713927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
572ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
5733927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
5743927de2eSStefano Zampini   PetscInt        lrows,lcols;
5753927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
5763927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
5773927de2eSStefano Zampini   PetscBool       isdense,issbaij;
5783927de2eSStefano Zampini   PetscErrorCode  ierr;
5793927de2eSStefano Zampini 
5803927de2eSStefano Zampini   PetscFunctionBegin;
5813927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
5823927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
5833927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
5843927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
5853927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
5863927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
587ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
588ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
5897230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
590ecf5a873SStefano Zampini   } else {
591ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
592ecf5a873SStefano Zampini   }
593ecf5a873SStefano Zampini 
5943927de2eSStefano Zampini   if (issbaij) {
5953927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
5963927de2eSStefano Zampini   }
5973927de2eSStefano Zampini   /*
598ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
5993927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
6003927de2eSStefano Zampini   */
6013927de2eSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
6023927de2eSStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
6033927de2eSStefano Zampini   }
6043927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
6053927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
6063927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
6073927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
6083927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
6093927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
6103927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
6113927de2eSStefano Zampini       row_ownership[j] = i;
6123927de2eSStefano Zampini     }
6133927de2eSStefano Zampini   }
6147230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
6153927de2eSStefano Zampini 
6163927de2eSStefano Zampini   /*
6173927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
6183927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
6193927de2eSStefano Zampini   */
6203927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
6213927de2eSStefano Zampini   /* preallocation as a MATAIJ */
6223927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
6233927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
624ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
6253927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
6263927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
627ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
6283927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
6293927de2eSStefano Zampini           my_dnz[i] += 1;
6303927de2eSStefano Zampini         } else { /* offdiag block */
6313927de2eSStefano Zampini           my_onz[i] += 1;
6323927de2eSStefano Zampini         }
6333927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
6343927de2eSStefano Zampini         if (i != j) {
6353927de2eSStefano Zampini           owner = row_ownership[index_col];
6363927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
6373927de2eSStefano Zampini             my_dnz[j] += 1;
6383927de2eSStefano Zampini           } else {
6393927de2eSStefano Zampini             my_onz[j] += 1;
6403927de2eSStefano Zampini           }
6413927de2eSStefano Zampini         }
6423927de2eSStefano Zampini       }
6433927de2eSStefano Zampini     }
644bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
645bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
646bb1015c3SStefano Zampini     PetscBool      done;
647bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
648bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
649bb1015c3SStefano Zampini     jptr = jj;
650bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
651bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
652bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
653bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
654bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
655bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
656bb1015c3SStefano Zampini           my_dnz[i] += 1;
657bb1015c3SStefano Zampini         } else { /* offdiag block */
658bb1015c3SStefano Zampini           my_onz[i] += 1;
659bb1015c3SStefano Zampini         }
660bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
661bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
662bb1015c3SStefano Zampini           owner = row_ownership[index_col];
663bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
664bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
665bb1015c3SStefano Zampini           } else {
666bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
667bb1015c3SStefano Zampini           }
668bb1015c3SStefano Zampini         }
669bb1015c3SStefano Zampini       }
670bb1015c3SStefano Zampini     }
671bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
672bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
673bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
6743927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
6753927de2eSStefano Zampini       const PetscInt *cols;
676ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
6773927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
6783927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
6793927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
680ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
6813927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
6823927de2eSStefano Zampini           my_dnz[i] += 1;
6833927de2eSStefano Zampini         } else { /* offdiag block */
6843927de2eSStefano Zampini           my_onz[i] += 1;
6853927de2eSStefano Zampini         }
6863927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
687d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
6883927de2eSStefano Zampini           owner = row_ownership[index_col];
6893927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
690d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
6913927de2eSStefano Zampini           } else {
692d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
6933927de2eSStefano Zampini           }
6943927de2eSStefano Zampini         }
6953927de2eSStefano Zampini       }
6963927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
6973927de2eSStefano Zampini     }
6983927de2eSStefano Zampini   }
699ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
700ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
7017230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
702ecf5a873SStefano Zampini   }
7033927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
704ecf5a873SStefano Zampini 
705ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
7063927de2eSStefano Zampini   if (maxreduce) {
7073927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
7083927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
709bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
7103927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
7113927de2eSStefano Zampini   } else {
7123927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
7133927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
714bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
7153927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
7163927de2eSStefano Zampini   }
7173927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
7183927de2eSStefano Zampini 
7193927de2eSStefano Zampini   /* Resize preallocation if overestimated */
7203927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
7213927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
7223927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
7233927de2eSStefano Zampini   }
7243927de2eSStefano Zampini   /* set preallocation */
7253927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
7263927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
7273927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
7283927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
7293927de2eSStefano Zampini   }
7303927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
7313927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
7323927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
7333927de2eSStefano Zampini   if (issbaij) {
7343927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
7353927de2eSStefano Zampini   }
7363927de2eSStefano Zampini   PetscFunctionReturn(0);
7373927de2eSStefano Zampini }
7383927de2eSStefano Zampini 
7393927de2eSStefano Zampini #undef __FUNCT__
740b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
7417230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
742b7ce53b6SStefano Zampini {
743b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
744d9a9e74cSStefano Zampini   Mat            local_mat;
745b7ce53b6SStefano Zampini   /* info on mat */
7463cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
747b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
748686e3a49SStefano Zampini   PetscBool      isdense,issbaij,isseqaij;
7497c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
750b7ce53b6SStefano Zampini   /* values insertion */
751b7ce53b6SStefano Zampini   PetscScalar    *array;
752b7ce53b6SStefano Zampini   /* work */
753b7ce53b6SStefano Zampini   PetscErrorCode ierr;
754b7ce53b6SStefano Zampini 
755b7ce53b6SStefano Zampini   PetscFunctionBegin;
756b7ce53b6SStefano Zampini   /* get info from mat */
7577c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
7587c03b4e8SStefano Zampini   if (nsubdomains == 1) {
7597c03b4e8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
7607c03b4e8SStefano Zampini       ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&(*M));CHKERRQ(ierr);
7617c03b4e8SStefano Zampini     } else {
7627c03b4e8SStefano Zampini       ierr = MatCopy(matis->A,*M,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
7637c03b4e8SStefano Zampini     }
7647c03b4e8SStefano Zampini     PetscFunctionReturn(0);
7657c03b4e8SStefano Zampini   }
766b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
767b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
7683cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
769b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
770b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
771686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
772b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
773b7ce53b6SStefano Zampini 
774b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
775b7ce53b6SStefano Zampini     MatType     new_mat_type;
7763927de2eSStefano Zampini     PetscBool   issbaij_red;
777b7ce53b6SStefano Zampini 
778b7ce53b6SStefano Zampini     /* determining new matrix type */
779b2566f29SBarry Smith     ierr = MPIU_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
780b7ce53b6SStefano Zampini     if (issbaij_red) {
781b7ce53b6SStefano Zampini       new_mat_type = MATSBAIJ;
782b7ce53b6SStefano Zampini     } else {
783b7ce53b6SStefano Zampini       if (bs>1) {
784b7ce53b6SStefano Zampini         new_mat_type = MATBAIJ;
785b7ce53b6SStefano Zampini       } else {
786b7ce53b6SStefano Zampini         new_mat_type = MATAIJ;
787b7ce53b6SStefano Zampini       }
788b7ce53b6SStefano Zampini     }
789b7ce53b6SStefano Zampini 
7903927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
7913cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
7923927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
7933927de2eSStefano Zampini     ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr);
7943927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
795b7ce53b6SStefano Zampini   } else {
7963cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
797b7ce53b6SStefano Zampini     /* some checks */
798b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
799b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
8003cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
8016c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
8026c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
8036c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
8046c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
8056c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
806b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
807b7ce53b6SStefano Zampini   }
808d9a9e74cSStefano Zampini 
809d9a9e74cSStefano Zampini   if (issbaij) {
810d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
811d9a9e74cSStefano Zampini   } else {
812d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
813d9a9e74cSStefano Zampini     local_mat = matis->A;
814d9a9e74cSStefano Zampini   }
815686e3a49SStefano Zampini 
816b7ce53b6SStefano Zampini   /* Set values */
817ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
818b7ce53b6SStefano Zampini   if (isdense) { /* special case for dense local matrices */
819ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
820ecf5a873SStefano Zampini 
821ecf5a873SStefano Zampini     if (local_rows != local_cols) {
822ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
823ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
824ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
825ecf5a873SStefano Zampini     } else {
826ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
827ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
828ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
829ecf5a873SStefano Zampini     }
830b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
831d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
832ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
833d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
834ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
835ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
836ecf5a873SStefano Zampini     } else {
837ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
838ecf5a873SStefano Zampini     }
839686e3a49SStefano Zampini   } else if (isseqaij) {
840ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
841686e3a49SStefano Zampini     PetscBool done;
842686e3a49SStefano Zampini 
843d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
844bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
845d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
846686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
847ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
848686e3a49SStefano Zampini     }
849d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
850bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
851d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
852686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
853ecf5a873SStefano Zampini     PetscInt i;
854c0962df8SStefano Zampini 
855686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
856686e3a49SStefano Zampini       PetscInt       j;
857ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
858686e3a49SStefano Zampini 
859ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
860ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
861ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
862686e3a49SStefano Zampini     }
863b7ce53b6SStefano Zampini   }
864b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
865d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
866b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
867b7ce53b6SStefano Zampini   if (isdense) {
868b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
869b7ce53b6SStefano Zampini   }
870b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
871b7ce53b6SStefano Zampini }
872b7ce53b6SStefano Zampini 
873b7ce53b6SStefano Zampini #undef __FUNCT__
874b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
875b7ce53b6SStefano Zampini /*@
876b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
877b7ce53b6SStefano Zampini 
878b7ce53b6SStefano Zampini   Input Parameter:
879b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
880b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
881b7ce53b6SStefano Zampini 
882b7ce53b6SStefano Zampini   Output Parameter:
883b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
884b7ce53b6SStefano Zampini 
885b7ce53b6SStefano Zampini   Level: developer
886b7ce53b6SStefano Zampini 
887eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
888b7ce53b6SStefano Zampini 
889b7ce53b6SStefano Zampini .seealso: MATIS
890b7ce53b6SStefano Zampini @*/
891b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
892b7ce53b6SStefano Zampini {
893b7ce53b6SStefano Zampini   PetscErrorCode ierr;
894b7ce53b6SStefano Zampini 
895b7ce53b6SStefano Zampini   PetscFunctionBegin;
896b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
897b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
898b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
899b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
900b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
901b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
9026c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
903b7ce53b6SStefano Zampini   }
904b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
905b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
906b7ce53b6SStefano Zampini }
907b7ce53b6SStefano Zampini 
908b7ce53b6SStefano Zampini #undef __FUNCT__
909ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
910ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
911ad6194a2SStefano Zampini {
912ad6194a2SStefano Zampini   PetscErrorCode ierr;
913ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
914ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
915ad6194a2SStefano Zampini   Mat            B,localmat;
916ad6194a2SStefano Zampini 
917ad6194a2SStefano Zampini   PetscFunctionBegin;
918ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
919ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
920ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
921e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
922ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
923ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
924b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
925ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
926ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
927ad6194a2SStefano Zampini   *newmat = B;
928ad6194a2SStefano Zampini   PetscFunctionReturn(0);
929ad6194a2SStefano Zampini }
930ad6194a2SStefano Zampini 
931ad6194a2SStefano Zampini #undef __FUNCT__
93269796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
933a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
93469796d55SStefano Zampini {
93569796d55SStefano Zampini   PetscErrorCode ierr;
93669796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
93769796d55SStefano Zampini   PetscBool      local_sym;
93869796d55SStefano Zampini 
93969796d55SStefano Zampini   PetscFunctionBegin;
94069796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
941b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
94269796d55SStefano Zampini   PetscFunctionReturn(0);
94369796d55SStefano Zampini }
94469796d55SStefano Zampini 
94569796d55SStefano Zampini #undef __FUNCT__
94669796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
947a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
94869796d55SStefano Zampini {
94969796d55SStefano Zampini   PetscErrorCode ierr;
95069796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
95169796d55SStefano Zampini   PetscBool      local_sym;
95269796d55SStefano Zampini 
95369796d55SStefano Zampini   PetscFunctionBegin;
95469796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
955b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
95669796d55SStefano Zampini   PetscFunctionReturn(0);
95769796d55SStefano Zampini }
95869796d55SStefano Zampini 
95969796d55SStefano Zampini #undef __FUNCT__
960b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
961a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
962b4319ba4SBarry Smith {
963dfbe8321SBarry Smith   PetscErrorCode ierr;
964b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
965b4319ba4SBarry Smith 
966b4319ba4SBarry Smith   PetscFunctionBegin;
9676bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
968e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
969e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
9706bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
9716bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
9723fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
973a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
974a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
975a8116848SStefano Zampini   if (b->sf != b->csf) {
976a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
977a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
978a8116848SStefano Zampini   }
97928f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
98028f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
981bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
982dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
983bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
984b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
985b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
9862e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
987b4319ba4SBarry Smith   PetscFunctionReturn(0);
988b4319ba4SBarry Smith }
989b4319ba4SBarry Smith 
990b4319ba4SBarry Smith #undef __FUNCT__
991b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
992a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
993b4319ba4SBarry Smith {
994dfbe8321SBarry Smith   PetscErrorCode ierr;
995b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
996b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
997b4319ba4SBarry Smith 
998b4319ba4SBarry Smith   PetscFunctionBegin;
999b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1000e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1001e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1002b4319ba4SBarry Smith 
1003b4319ba4SBarry Smith   /* multiply the local matrix */
1004b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1005b4319ba4SBarry Smith 
1006b4319ba4SBarry Smith   /* scatter product back into global memory */
10072dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1008e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1009e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1010b4319ba4SBarry Smith   PetscFunctionReturn(0);
1011b4319ba4SBarry Smith }
1012b4319ba4SBarry Smith 
1013b4319ba4SBarry Smith #undef __FUNCT__
10142e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
1015a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
10162e74eeadSLisandro Dalcin {
1017650997f4SStefano Zampini   Vec            temp_vec;
10182e74eeadSLisandro Dalcin   PetscErrorCode ierr;
10192e74eeadSLisandro Dalcin 
10202e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1021650997f4SStefano Zampini   if (v3 != v2) {
1022650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1023650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1024650997f4SStefano Zampini   } else {
1025650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1026650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1027650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1028650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1029650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1030650997f4SStefano Zampini   }
10312e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
10322e74eeadSLisandro Dalcin }
10332e74eeadSLisandro Dalcin 
10342e74eeadSLisandro Dalcin #undef __FUNCT__
10352e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
1036a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
10372e74eeadSLisandro Dalcin {
10382e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
10392e74eeadSLisandro Dalcin   PetscErrorCode ierr;
10402e74eeadSLisandro Dalcin 
1041e176bc59SStefano Zampini   PetscFunctionBegin;
10422e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1043e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1044e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10452e74eeadSLisandro Dalcin 
10462e74eeadSLisandro Dalcin   /* multiply the local matrix */
1047e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
10482e74eeadSLisandro Dalcin 
10492e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1050e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1051e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1052e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10532e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
10542e74eeadSLisandro Dalcin }
10552e74eeadSLisandro Dalcin 
10562e74eeadSLisandro Dalcin #undef __FUNCT__
10572e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
1058a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
10592e74eeadSLisandro Dalcin {
1060650997f4SStefano Zampini   Vec            temp_vec;
10612e74eeadSLisandro Dalcin   PetscErrorCode ierr;
10622e74eeadSLisandro Dalcin 
10632e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1064650997f4SStefano Zampini   if (v3 != v2) {
1065650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1066650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1067650997f4SStefano Zampini   } else {
1068650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1069650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1070650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1071650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1072650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1073650997f4SStefano Zampini   }
10742e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
10752e74eeadSLisandro Dalcin }
10762e74eeadSLisandro Dalcin 
10772e74eeadSLisandro Dalcin #undef __FUNCT__
1078b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
1079a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1080b4319ba4SBarry Smith {
1081b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1082dfbe8321SBarry Smith   PetscErrorCode ierr;
1083b4319ba4SBarry Smith   PetscViewer    sviewer;
1084b4319ba4SBarry Smith 
1085b4319ba4SBarry Smith   PetscFunctionBegin;
10863f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1087b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
10883f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
10896e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1090b4319ba4SBarry Smith   PetscFunctionReturn(0);
1091b4319ba4SBarry Smith }
1092b4319ba4SBarry Smith 
1093b4319ba4SBarry Smith #undef __FUNCT__
1094b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
1095a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1096b4319ba4SBarry Smith {
1097dfbe8321SBarry Smith   PetscErrorCode ierr;
1098e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1099b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1100b4319ba4SBarry Smith   IS             from,to;
1101e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1102b4319ba4SBarry Smith 
1103b4319ba4SBarry Smith   PetscFunctionBegin;
1104784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1105e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
11063bbff08aSStefano Zampini   /* Destroy any previous data */
110770cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
110870cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
11093fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1110e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1111e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
11121c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
111328f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
111428f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
11153bbff08aSStefano Zampini 
11163bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1117fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1118fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1119fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1120fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1121b4319ba4SBarry Smith 
1122b4319ba4SBarry Smith   /* Create the local matrix A */
1123e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1124e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1125e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1126e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1127f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1128e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1129e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1130e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1131ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1132ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1133b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1134b4319ba4SBarry Smith 
1135f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1136b4319ba4SBarry Smith     /* Create the local work vectors */
11373bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1138b4319ba4SBarry Smith 
1139e176bc59SStefano Zampini     /* setup the global to local scatters */
1140e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1141e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1142784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1143e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1144e176bc59SStefano Zampini     if (rmapping != cmapping) {
1145e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1146e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1147e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1148e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1149e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1150e176bc59SStefano Zampini     } else {
1151e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1152e176bc59SStefano Zampini       is->cctx = is->rctx;
1153e176bc59SStefano Zampini     }
11543fd1c9e7SStefano Zampini 
11553fd1c9e7SStefano Zampini     /* interface counter vector (local) */
11563fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
11573fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
11583fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11593fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11603fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11613fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11623fd1c9e7SStefano Zampini 
11633fd1c9e7SStefano Zampini     /* free workspace */
1164e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1165e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
11666bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
11676bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1168f26d0771SStefano Zampini   }
116948ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1170b4319ba4SBarry Smith   PetscFunctionReturn(0);
1171b4319ba4SBarry Smith }
1172b4319ba4SBarry Smith 
11732e74eeadSLisandro Dalcin #undef __FUNCT__
11742e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
1175a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
11762e74eeadSLisandro Dalcin {
11772e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
11782e74eeadSLisandro Dalcin   PetscErrorCode ierr;
117997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
118097563a80SStefano Zampini   PetscInt       i,zm,zn;
118197563a80SStefano Zampini #endif
1182f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
11832e74eeadSLisandro Dalcin 
11842e74eeadSLisandro Dalcin   PetscFunctionBegin;
11852e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1186f26d0771SStefano 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);
118797563a80SStefano Zampini   /* count negative indices */
118897563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
118997563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
11902e74eeadSLisandro Dalcin #endif
119197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
119297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
119397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
119497563a80SStefano Zampini   /* count negative indices (should be the same as before) */
119597563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
119697563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
119797563a80SStefano 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");
119897563a80SStefano 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");
119997563a80SStefano Zampini #endif
12002e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
12012e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
12022e74eeadSLisandro Dalcin }
12032e74eeadSLisandro Dalcin 
1204b4319ba4SBarry Smith #undef __FUNCT__
120597563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS"
1206a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
120797563a80SStefano Zampini {
120897563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
120997563a80SStefano Zampini   PetscErrorCode ierr;
121097563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
121197563a80SStefano Zampini   PetscInt       i,zm,zn;
121297563a80SStefano Zampini #endif
1213f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
121497563a80SStefano Zampini 
121597563a80SStefano Zampini   PetscFunctionBegin;
121697563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1217f26d0771SStefano 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);
121897563a80SStefano Zampini   /* count negative indices */
121997563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
122097563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
122197563a80SStefano Zampini #endif
122297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
122397563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
122497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
122597563a80SStefano Zampini   /* count negative indices (should be the same as before) */
122697563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
122797563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
122897563a80SStefano 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");
122997563a80SStefano 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");
123097563a80SStefano Zampini #endif
123197563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
123297563a80SStefano Zampini   PetscFunctionReturn(0);
123397563a80SStefano Zampini }
123497563a80SStefano Zampini 
123597563a80SStefano Zampini #undef __FUNCT__
1236b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
1237a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1238b4319ba4SBarry Smith {
1239dfbe8321SBarry Smith   PetscErrorCode ierr;
1240b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1241b4319ba4SBarry Smith 
1242b4319ba4SBarry Smith   PetscFunctionBegin;
1243b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1244b4319ba4SBarry Smith   PetscFunctionReturn(0);
1245b4319ba4SBarry Smith }
1246b4319ba4SBarry Smith 
1247b4319ba4SBarry Smith #undef __FUNCT__
1248f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
1249a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1250f0006bf2SLisandro Dalcin {
1251f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1252f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1253f0006bf2SLisandro Dalcin 
1254f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1255f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1256f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1257f0006bf2SLisandro Dalcin }
1258f0006bf2SLisandro Dalcin 
1259f0006bf2SLisandro Dalcin #undef __FUNCT__
1260f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private"
1261f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1262f0ae7da4SStefano Zampini {
1263f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1264f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1265f0ae7da4SStefano Zampini 
1266f0ae7da4SStefano Zampini   PetscFunctionBegin;
1267f0ae7da4SStefano Zampini   if (!n) {
1268f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1269f0ae7da4SStefano Zampini   } else {
1270f0ae7da4SStefano Zampini     PetscInt i;
1271f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1272f0ae7da4SStefano Zampini 
1273f0ae7da4SStefano Zampini     if (columns) {
1274f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1275f0ae7da4SStefano Zampini     } else {
1276f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1277f0ae7da4SStefano Zampini     }
1278f0ae7da4SStefano Zampini     if (diag != 0.) {
1279f0ae7da4SStefano Zampini       const PetscScalar *array;
1280f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1281f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1282f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1283f0ae7da4SStefano Zampini       }
1284f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1285f0ae7da4SStefano Zampini     }
1286f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1287f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1288f0ae7da4SStefano Zampini   }
1289f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1290f0ae7da4SStefano Zampini }
1291f0ae7da4SStefano Zampini 
1292f0ae7da4SStefano Zampini #undef __FUNCT__
1293f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS"
1294f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
12952e74eeadSLisandro Dalcin {
12966e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
12976e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
12986e520ac8SStefano Zampini   PetscInt       *lrows;
12992e74eeadSLisandro Dalcin   PetscErrorCode ierr;
13002e74eeadSLisandro Dalcin 
13012e74eeadSLisandro Dalcin   PetscFunctionBegin;
1302f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1303f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1304f0ae7da4SStefano Zampini     PetscBool cong;
1305f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1306f0ae7da4SStefano 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");
1307f0ae7da4SStefano 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");
1308f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1309f0ae7da4SStefano Zampini   }
1310f0ae7da4SStefano Zampini #endif
13116e520ac8SStefano Zampini   /* get locally owned rows */
1312f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
13136e520ac8SStefano Zampini   /* fix right hand side if needed */
13146e520ac8SStefano Zampini   if (x && b) {
13156e520ac8SStefano Zampini     const PetscScalar *xx;
13166e520ac8SStefano Zampini     PetscScalar       *bb;
13176e520ac8SStefano Zampini 
13186e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
13196e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
13206e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
13216e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
13226e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
13232e74eeadSLisandro Dalcin   }
13246e520ac8SStefano Zampini   /* get rows associated to the local matrices */
13256e520ac8SStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
13266e520ac8SStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
13276e520ac8SStefano Zampini   }
13286e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
13296e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
13306e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
13316e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
13326e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
13336e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
13346e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
13356e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
13366e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1337f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
13386e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
13392e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
13402e74eeadSLisandro Dalcin }
13412e74eeadSLisandro Dalcin 
13422e74eeadSLisandro Dalcin #undef __FUNCT__
1343f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS"
1344f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1345b4319ba4SBarry Smith {
1346dfbe8321SBarry Smith   PetscErrorCode ierr;
1347b4319ba4SBarry Smith 
1348b4319ba4SBarry Smith   PetscFunctionBegin;
1349f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1350f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1351f0ae7da4SStefano Zampini }
13522205254eSKarl Rupp 
1353f0ae7da4SStefano Zampini #undef __FUNCT__
1354f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS"
1355f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1356f0ae7da4SStefano Zampini {
1357f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1358f0ae7da4SStefano Zampini 
1359f0ae7da4SStefano Zampini   PetscFunctionBegin;
1360f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1361b4319ba4SBarry Smith   PetscFunctionReturn(0);
1362b4319ba4SBarry Smith }
1363b4319ba4SBarry Smith 
1364b4319ba4SBarry Smith #undef __FUNCT__
1365b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
1366a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1367b4319ba4SBarry Smith {
1368b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1369dfbe8321SBarry Smith   PetscErrorCode ierr;
1370b4319ba4SBarry Smith 
1371b4319ba4SBarry Smith   PetscFunctionBegin;
1372b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1373b4319ba4SBarry Smith   PetscFunctionReturn(0);
1374b4319ba4SBarry Smith }
1375b4319ba4SBarry Smith 
1376b4319ba4SBarry Smith #undef __FUNCT__
1377b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
1378a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1379b4319ba4SBarry Smith {
1380b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1381dfbe8321SBarry Smith   PetscErrorCode ierr;
1382b4319ba4SBarry Smith 
1383b4319ba4SBarry Smith   PetscFunctionBegin;
1384b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1385b4319ba4SBarry Smith   PetscFunctionReturn(0);
1386b4319ba4SBarry Smith }
1387b4319ba4SBarry Smith 
1388b4319ba4SBarry Smith #undef __FUNCT__
1389b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
1390a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1391b4319ba4SBarry Smith {
1392b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1393b4319ba4SBarry Smith 
1394b4319ba4SBarry Smith   PetscFunctionBegin;
1395b4319ba4SBarry Smith   *local = is->A;
1396b4319ba4SBarry Smith   PetscFunctionReturn(0);
1397b4319ba4SBarry Smith }
1398b4319ba4SBarry Smith 
1399b4319ba4SBarry Smith #undef __FUNCT__
1400b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
1401b4319ba4SBarry Smith /*@
1402b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1403b4319ba4SBarry Smith 
1404b4319ba4SBarry Smith   Input Parameter:
1405b4319ba4SBarry Smith .  mat - the matrix
1406b4319ba4SBarry Smith 
1407b4319ba4SBarry Smith   Output Parameter:
1408eb82efa4SStefano Zampini .  local - the local matrix
1409b4319ba4SBarry Smith 
1410b4319ba4SBarry Smith   Level: advanced
1411b4319ba4SBarry Smith 
1412b4319ba4SBarry Smith   Notes:
1413b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1414b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1415b4319ba4SBarry Smith   of the MatSetValues() operation.
1416b4319ba4SBarry Smith 
1417b4319ba4SBarry Smith .seealso: MATIS
1418b4319ba4SBarry Smith @*/
14197087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1420b4319ba4SBarry Smith {
14214ac538c5SBarry Smith   PetscErrorCode ierr;
1422b4319ba4SBarry Smith 
1423b4319ba4SBarry Smith   PetscFunctionBegin;
14240700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1425b4319ba4SBarry Smith   PetscValidPointer(local,2);
14264ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1427b4319ba4SBarry Smith   PetscFunctionReturn(0);
1428b4319ba4SBarry Smith }
1429b4319ba4SBarry Smith 
14303b03a366Sstefano_zampini #undef __FUNCT__
14313b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
1432a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
14333b03a366Sstefano_zampini {
14343b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
14353b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
14363b03a366Sstefano_zampini   PetscErrorCode ierr;
14373b03a366Sstefano_zampini 
14383b03a366Sstefano_zampini   PetscFunctionBegin;
14394e4c7dbeSStefano Zampini   if (is->A) {
14403b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
14413b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1442f0ae7da4SStefano 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);
14434e4c7dbeSStefano Zampini   }
14443b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
14453b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
14463b03a366Sstefano_zampini   is->A = local;
14473b03a366Sstefano_zampini   PetscFunctionReturn(0);
14483b03a366Sstefano_zampini }
14493b03a366Sstefano_zampini 
14503b03a366Sstefano_zampini #undef __FUNCT__
14513b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
14523b03a366Sstefano_zampini /*@
1453eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
14543b03a366Sstefano_zampini 
14553b03a366Sstefano_zampini   Input Parameter:
14563b03a366Sstefano_zampini .  mat - the matrix
1457eb82efa4SStefano Zampini .  local - the local matrix
14583b03a366Sstefano_zampini 
14593b03a366Sstefano_zampini   Output Parameter:
14603b03a366Sstefano_zampini 
14613b03a366Sstefano_zampini   Level: advanced
14623b03a366Sstefano_zampini 
14633b03a366Sstefano_zampini   Notes:
14643b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
14653b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
14663b03a366Sstefano_zampini 
14673b03a366Sstefano_zampini .seealso: MATIS
14683b03a366Sstefano_zampini @*/
14693b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
14703b03a366Sstefano_zampini {
14713b03a366Sstefano_zampini   PetscErrorCode ierr;
14723b03a366Sstefano_zampini 
14733b03a366Sstefano_zampini   PetscFunctionBegin;
14743b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1475b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
14763b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
14773b03a366Sstefano_zampini   PetscFunctionReturn(0);
14783b03a366Sstefano_zampini }
14793b03a366Sstefano_zampini 
14806726f965SBarry Smith #undef __FUNCT__
14816726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
1482a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
14836726f965SBarry Smith {
14846726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
14856726f965SBarry Smith   PetscErrorCode ierr;
14866726f965SBarry Smith 
14876726f965SBarry Smith   PetscFunctionBegin;
14886726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
14896726f965SBarry Smith   PetscFunctionReturn(0);
14906726f965SBarry Smith }
14916726f965SBarry Smith 
14926726f965SBarry Smith #undef __FUNCT__
14932e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
1494a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
14952e74eeadSLisandro Dalcin {
14962e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
14972e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14982e74eeadSLisandro Dalcin 
14992e74eeadSLisandro Dalcin   PetscFunctionBegin;
15002e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
15012e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15022e74eeadSLisandro Dalcin }
15032e74eeadSLisandro Dalcin 
15042e74eeadSLisandro Dalcin #undef __FUNCT__
15052e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
1506a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
15072e74eeadSLisandro Dalcin {
15082e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
15092e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15102e74eeadSLisandro Dalcin 
15112e74eeadSLisandro Dalcin   PetscFunctionBegin;
15122e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
1513e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
15142e74eeadSLisandro Dalcin 
15152e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
15162e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
1517e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1518e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15192e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15202e74eeadSLisandro Dalcin }
15212e74eeadSLisandro Dalcin 
15222e74eeadSLisandro Dalcin #undef __FUNCT__
15236726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
1524a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
15256726f965SBarry Smith {
15266726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
15276726f965SBarry Smith   PetscErrorCode ierr;
15286726f965SBarry Smith 
15296726f965SBarry Smith   PetscFunctionBegin;
15304e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
15316726f965SBarry Smith   PetscFunctionReturn(0);
15326726f965SBarry Smith }
15336726f965SBarry Smith 
1534284134d9SBarry Smith #undef __FUNCT__
1535f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS"
1536f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
1537f26d0771SStefano Zampini {
1538f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
1539f26d0771SStefano Zampini   Mat_IS         *x;
1540f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1541f26d0771SStefano Zampini   PetscBool      ismatis;
1542f26d0771SStefano Zampini #endif
1543f26d0771SStefano Zampini   PetscErrorCode ierr;
1544f26d0771SStefano Zampini 
1545f26d0771SStefano Zampini   PetscFunctionBegin;
1546f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1547f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
1548f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
1549f26d0771SStefano Zampini #endif
1550f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
1551f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
1552f26d0771SStefano Zampini   PetscFunctionReturn(0);
1553f26d0771SStefano Zampini }
1554f26d0771SStefano Zampini 
1555f26d0771SStefano Zampini #undef __FUNCT__
1556f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS"
1557f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
1558f26d0771SStefano Zampini {
1559f26d0771SStefano Zampini   Mat                    lA;
1560f26d0771SStefano Zampini   Mat_IS                 *matis;
1561f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
1562f26d0771SStefano Zampini   IS                     is;
1563f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
1564f26d0771SStefano Zampini   PetscInt               nrg;
1565f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
1566f26d0771SStefano Zampini   PetscErrorCode         ierr;
1567f26d0771SStefano Zampini 
1568f26d0771SStefano Zampini   PetscFunctionBegin;
1569f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1570f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
1571f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
1572f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
1573f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1574f0ae7da4SStefano 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);
1575f26d0771SStefano Zampini #endif
1576f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
1577f26d0771SStefano Zampini   /* map from [0,nrl) to row */
1578f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
1579f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1580f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
1581f26d0771SStefano Zampini #else
1582f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
1583f26d0771SStefano Zampini #endif
1584f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
1585f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1586f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1587f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1588f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
1589f26d0771SStefano Zampini   /* compute new l2g map for columns */
1590f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
1591f26d0771SStefano Zampini     const PetscInt *cg,*cl;
1592f26d0771SStefano Zampini     PetscInt       ncg;
1593f26d0771SStefano Zampini     PetscInt       ncl;
1594f26d0771SStefano Zampini 
1595f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1596f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
1597f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
1598f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
1599f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1600f0ae7da4SStefano 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);
1601f26d0771SStefano Zampini #endif
1602f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
1603f26d0771SStefano Zampini     /* map from [0,ncl) to col */
1604f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
1605f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1606f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
1607f26d0771SStefano Zampini #else
1608f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
1609f26d0771SStefano Zampini #endif
1610f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
1611f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1612f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1613f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1614f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1615f26d0771SStefano Zampini   } else {
1616f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
1617f26d0771SStefano Zampini     cl2g = rl2g;
1618f26d0771SStefano Zampini   }
1619f26d0771SStefano Zampini   /* create the MATIS submatrix */
1620f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
1621f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
1622f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1623f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
1624b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
1625f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
1626f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
1627f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1628f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
1629f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
1630f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1631f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1632f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1633f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1634f26d0771SStefano Zampini   /* remove unsupported ops */
1635f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1636f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
1637f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
1638f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
1639f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
1640f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
1641f26d0771SStefano Zampini   PetscFunctionReturn(0);
1642f26d0771SStefano Zampini }
1643f26d0771SStefano Zampini 
1644f26d0771SStefano Zampini #undef __FUNCT__
1645284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
1646284134d9SBarry Smith /*@
16473c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
1648284134d9SBarry Smith        process but not across processes.
1649284134d9SBarry Smith 
1650284134d9SBarry Smith    Input Parameters:
1651284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
1652e176bc59SStefano Zampini .     bs      - block size of the matrix
1653df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
1654e176bc59SStefano Zampini .     rmap    - local to global map for rows
1655e176bc59SStefano Zampini -     cmap    - local to global map for cols
1656284134d9SBarry Smith 
1657284134d9SBarry Smith    Output Parameter:
1658284134d9SBarry Smith .    A - the resulting matrix
1659284134d9SBarry Smith 
16608e6c10adSSatish Balay    Level: advanced
16618e6c10adSSatish Balay 
16623c212e90SHong Zhang    Notes: See MATIS for more details.
16636fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
16646fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
16653c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
1666284134d9SBarry Smith 
1667284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
1668284134d9SBarry Smith @*/
1669e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
1670284134d9SBarry Smith {
1671284134d9SBarry Smith   PetscErrorCode ierr;
1672284134d9SBarry Smith 
1673284134d9SBarry Smith   PetscFunctionBegin;
16746fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
1675284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
16766fdf41d1SStefano Zampini   if (bs > 0) {
1677d3ee2243SStefano Zampini     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
16786fdf41d1SStefano Zampini   }
1679284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
1680284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
1681e176bc59SStefano Zampini   if (rmap && cmap) {
1682e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
1683e176bc59SStefano Zampini   } else if (!rmap) {
1684e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
1685e176bc59SStefano Zampini   } else {
1686e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
1687e176bc59SStefano Zampini   }
1688284134d9SBarry Smith   PetscFunctionReturn(0);
1689284134d9SBarry Smith }
1690284134d9SBarry Smith 
1691b4319ba4SBarry Smith /*MC
1692f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
1693b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
1694b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
1695b4319ba4SBarry Smith    product is handled "implicitly".
1696b4319ba4SBarry Smith 
1697b4319ba4SBarry Smith    Operations Provided:
16986726f965SBarry Smith +  MatMult()
16992e74eeadSLisandro Dalcin .  MatMultAdd()
17002e74eeadSLisandro Dalcin .  MatMultTranspose()
17012e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
17026726f965SBarry Smith .  MatZeroEntries()
17036726f965SBarry Smith .  MatSetOption()
17042e74eeadSLisandro Dalcin .  MatZeroRows()
17052e74eeadSLisandro Dalcin .  MatSetValues()
170697563a80SStefano Zampini .  MatSetValuesBlocked()
17076726f965SBarry Smith .  MatSetValuesLocal()
170897563a80SStefano Zampini .  MatSetValuesBlockedLocal()
17092e74eeadSLisandro Dalcin .  MatScale()
17102e74eeadSLisandro Dalcin .  MatGetDiagonal()
17112b404112SStefano Zampini .  MatMissingDiagonal()
17122b404112SStefano Zampini .  MatDuplicate()
17132b404112SStefano Zampini .  MatCopy()
1714f26d0771SStefano Zampini .  MatAXPY()
1715f26d0771SStefano Zampini .  MatGetSubMatrix()
1716f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
1717d7f69cd0SStefano Zampini .  MatTranspose()
17186726f965SBarry Smith -  MatSetLocalToGlobalMapping()
1719b4319ba4SBarry Smith 
1720b4319ba4SBarry Smith    Options Database Keys:
1721b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
1722b4319ba4SBarry Smith 
1723b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
1724b4319ba4SBarry Smith 
1725b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
1726b4319ba4SBarry Smith 
1727b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
1728eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
1729b4319ba4SBarry Smith 
1730b4319ba4SBarry Smith   Level: advanced
1731b4319ba4SBarry Smith 
1732f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
1733b4319ba4SBarry Smith 
1734b4319ba4SBarry Smith M*/
1735b4319ba4SBarry Smith 
1736b4319ba4SBarry Smith #undef __FUNCT__
1737b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
17388cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
1739b4319ba4SBarry Smith {
1740dfbe8321SBarry Smith   PetscErrorCode ierr;
1741b4319ba4SBarry Smith   Mat_IS         *b;
1742b4319ba4SBarry Smith 
1743b4319ba4SBarry Smith   PetscFunctionBegin;
1744b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
1745b4319ba4SBarry Smith   A->data = (void*)b;
1746b4319ba4SBarry Smith 
1747e176bc59SStefano Zampini   /* matrix ops */
1748e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1749b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
17502e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
17512e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
17522e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
1753b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
1754b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
17552e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
175698921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
1757b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
1758f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
17592e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
1760f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
1761b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
1762b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
1763b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
17646726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
17652e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
17662e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
17676726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
176869796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
176969796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
1770ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
17716bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
17722b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
1773659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
1774a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
1775f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
17763fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
17773fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
1778d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
1779*7fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
1780b4319ba4SBarry Smith 
1781b7ce53b6SStefano Zampini   /* special MATIS functions */
1782bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
1783bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
1784b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
17852e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
178617667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
1787b4319ba4SBarry Smith   PetscFunctionReturn(0);
1788b4319ba4SBarry Smith }
1789