xref: /petsc/src/mat/impls/is/matis.c (revision 5e3038f0b9da9137880b21d632bc78638d2c5b08)
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*5e3038f0Sstefano_zampini #define __FUNCT__ "MatConvert_Nest_IS"
18*5e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
19*5e3038f0Sstefano_zampini {
20*5e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
21*5e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
22*5e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
23*5e3038f0Sstefano_zampini   MPI_Comm               comm;
24*5e3038f0Sstefano_zampini   PetscInt               *lr,*lc,*lrb,*lcb,*l2gidxs;
25*5e3038f0Sstefano_zampini   PetscInt               sti,stl,i,j,nr,nc,rbs,cbs;
26*5e3038f0Sstefano_zampini   PetscBool              convert,lreuse;
27*5e3038f0Sstefano_zampini   PetscErrorCode         ierr;
28*5e3038f0Sstefano_zampini 
29*5e3038f0Sstefano_zampini   PetscFunctionBeginUser;
30*5e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
31*5e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
32*5e3038f0Sstefano_zampini   rnest  = NULL;
33*5e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
34*5e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
35*5e3038f0Sstefano_zampini 
36*5e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
37*5e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
38*5e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
39*5e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
40*5e3038f0Sstefano_zampini     if (isnest) {
41*5e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
42*5e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
43*5e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
44*5e3038f0Sstefano_zampini     }
45*5e3038f0Sstefano_zampini   }
46*5e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
47*5e3038f0Sstefano_zampini   ierr = PetscCalloc4(nr,&lr,nc,&lc,nr,&lrb,nc,&lcb);CHKERRQ(ierr);
48*5e3038f0Sstefano_zampini   ierr = PetscCalloc5(nr,&isrow,nc,&iscol,
49*5e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
50*5e3038f0Sstefano_zampini                       nr*nc,&snest);CHKERRQ(ierr);
51*5e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
52*5e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
53*5e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
54*5e3038f0Sstefano_zampini       PetscBool ismatis;
55*5e3038f0Sstefano_zampini       PetscInt  l1,l2,ij=i*nc+j;
56*5e3038f0Sstefano_zampini 
57*5e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
58*5e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
59*5e3038f0Sstefano_zampini 
60*5e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
61*5e3038f0Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
62*5e3038f0Sstefano_zampini       if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) is not of type MATIS",i,j);
63*5e3038f0Sstefano_zampini 
64*5e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
65*5e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
66*5e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
67*5e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
68*5e3038f0Sstefano_zampini       if (lr[i] && l1 != lr[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lr[i],l1);
69*5e3038f0Sstefano_zampini       if (lc[j] && l2 != lc[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lc[j],l2);
70*5e3038f0Sstefano_zampini       lr[i] = l1;
71*5e3038f0Sstefano_zampini       lc[j] = l2;
72*5e3038f0Sstefano_zampini       ierr  = MatGetBlockSizes(snest[ij],&l1,&l2);CHKERRQ(ierr);
73*5e3038f0Sstefano_zampini       if (lrb[i] && l1 != lrb[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid block size %D != %D",i,j,lrb[i],l1);
74*5e3038f0Sstefano_zampini       if (lcb[j] && l2 != lcb[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid block size %D != %D",i,j,lcb[j],l2);
75*5e3038f0Sstefano_zampini       lrb[i] = l1;
76*5e3038f0Sstefano_zampini       lcb[j] = l2;
77*5e3038f0Sstefano_zampini 
78*5e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
79*5e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
80*5e3038f0Sstefano_zampini     }
81*5e3038f0Sstefano_zampini   }
82*5e3038f0Sstefano_zampini 
83*5e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
84*5e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
85*5e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
86*5e3038f0Sstefano_zampini     rl2g = NULL;
87*5e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
88*5e3038f0Sstefano_zampini       PetscInt n1,n2;
89*5e3038f0Sstefano_zampini 
90*5e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
91*5e3038f0Sstefano_zampini       ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
92*5e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
93*5e3038f0Sstefano_zampini       if (!n1) continue;
94*5e3038f0Sstefano_zampini       if (!rl2g) {
95*5e3038f0Sstefano_zampini         rl2g = cl2g;
96*5e3038f0Sstefano_zampini       } else {
97*5e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
98*5e3038f0Sstefano_zampini         PetscBool      same;
99*5e3038f0Sstefano_zampini 
100*5e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
101*5e3038f0Sstefano_zampini         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap size %D != %D",i,j,n1,n2);
102*5e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
103*5e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
104*5e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
105*5e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
106*5e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
107*5e3038f0Sstefano_zampini         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap",i,j);
108*5e3038f0Sstefano_zampini       }
109*5e3038f0Sstefano_zampini     }
110*5e3038f0Sstefano_zampini   }
111*5e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
112*5e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
113*5e3038f0Sstefano_zampini     rl2g = NULL;
114*5e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
115*5e3038f0Sstefano_zampini       PetscInt n1,n2;
116*5e3038f0Sstefano_zampini 
117*5e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
118*5e3038f0Sstefano_zampini       ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
119*5e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
120*5e3038f0Sstefano_zampini       if (!n1) continue;
121*5e3038f0Sstefano_zampini       if (!rl2g) {
122*5e3038f0Sstefano_zampini         rl2g = cl2g;
123*5e3038f0Sstefano_zampini       } else {
124*5e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
125*5e3038f0Sstefano_zampini         PetscBool      same;
126*5e3038f0Sstefano_zampini 
127*5e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
128*5e3038f0Sstefano_zampini         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap size %D != %D",j,i,n1,n2);
129*5e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
130*5e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
131*5e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
132*5e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
133*5e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
134*5e3038f0Sstefano_zampini         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap",j,i);
135*5e3038f0Sstefano_zampini       }
136*5e3038f0Sstefano_zampini     }
137*5e3038f0Sstefano_zampini   }
138*5e3038f0Sstefano_zampini #endif
139*5e3038f0Sstefano_zampini 
140*5e3038f0Sstefano_zampini   B = NULL;
141*5e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
142*5e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
143*5e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
144*5e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
145*5e3038f0Sstefano_zampini     for (i=0,sti=0,stl=0;i<nr;i++) {
146*5e3038f0Sstefano_zampini       Mat            usedmat;
147*5e3038f0Sstefano_zampini       Mat_IS         *matis;
148*5e3038f0Sstefano_zampini       const PetscInt *idxs;
149*5e3038f0Sstefano_zampini       PetscInt       n = lr[i]/lrb[i];
150*5e3038f0Sstefano_zampini 
151*5e3038f0Sstefano_zampini       /* local IS for local NEST */
152*5e3038f0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr);
153*5e3038f0Sstefano_zampini       sti  += n;
154*5e3038f0Sstefano_zampini 
155*5e3038f0Sstefano_zampini       /* l2gmap */
156*5e3038f0Sstefano_zampini       j = 0;
157*5e3038f0Sstefano_zampini       usedmat = nest[i][j];
158*5e3038f0Sstefano_zampini       while (!usedmat && j < nc) usedmat = nest[i][j++];
159*5e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
160*5e3038f0Sstefano_zampini       if (!matis->sf) {
161*5e3038f0Sstefano_zampini         ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr);
162*5e3038f0Sstefano_zampini       }
163*5e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
164*5e3038f0Sstefano_zampini       ierr  = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
165*5e3038f0Sstefano_zampini       ierr  = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
166*5e3038f0Sstefano_zampini       ierr  = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
167*5e3038f0Sstefano_zampini       stl += lr[i];
168*5e3038f0Sstefano_zampini     }
169*5e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
170*5e3038f0Sstefano_zampini 
171*5e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
172*5e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
173*5e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
174*5e3038f0Sstefano_zampini     for (i=0,sti=0,stl=0;i<nc;i++) {
175*5e3038f0Sstefano_zampini       Mat            usedmat;
176*5e3038f0Sstefano_zampini       Mat_IS         *matis;
177*5e3038f0Sstefano_zampini       const PetscInt *idxs;
178*5e3038f0Sstefano_zampini       PetscInt       n = lc[i]/lcb[i];
179*5e3038f0Sstefano_zampini 
180*5e3038f0Sstefano_zampini       /* local IS for local NEST */
181*5e3038f0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr);
182*5e3038f0Sstefano_zampini       sti  += n;
183*5e3038f0Sstefano_zampini 
184*5e3038f0Sstefano_zampini       /* l2gmap */
185*5e3038f0Sstefano_zampini       j = 0;
186*5e3038f0Sstefano_zampini       usedmat = nest[j][i];
187*5e3038f0Sstefano_zampini       while (!usedmat && j < nr) usedmat = nest[j++][i];
188*5e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
189*5e3038f0Sstefano_zampini       if (!matis->sf) {
190*5e3038f0Sstefano_zampini         ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr);
191*5e3038f0Sstefano_zampini       }
192*5e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
193*5e3038f0Sstefano_zampini       ierr  = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
194*5e3038f0Sstefano_zampini       ierr  = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
195*5e3038f0Sstefano_zampini       ierr  = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
196*5e3038f0Sstefano_zampini       stl += lc[i];
197*5e3038f0Sstefano_zampini     }
198*5e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
199*5e3038f0Sstefano_zampini 
200*5e3038f0Sstefano_zampini     /* Create MATIS */
201*5e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
202*5e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
203*5e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
204*5e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
205*5e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
206*5e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
207*5e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
208*5e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
209*5e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
210*5e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
211*5e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
212*5e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
213*5e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
214*5e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
215*5e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
216*5e3038f0Sstefano_zampini     } else {
217*5e3038f0Sstefano_zampini       *newmat = B;
218*5e3038f0Sstefano_zampini     }
219*5e3038f0Sstefano_zampini   } else {
220*5e3038f0Sstefano_zampini     if (lreuse) {
221*5e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
222*5e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
223*5e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
224*5e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
225*5e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
226*5e3038f0Sstefano_zampini           }
227*5e3038f0Sstefano_zampini         }
228*5e3038f0Sstefano_zampini       }
229*5e3038f0Sstefano_zampini     } else {
230*5e3038f0Sstefano_zampini       for (i=0,sti=0;i<nr;i++) {
231*5e3038f0Sstefano_zampini         PetscInt n = lr[i]/lrb[i];
232*5e3038f0Sstefano_zampini 
233*5e3038f0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr);
234*5e3038f0Sstefano_zampini         sti  += n;
235*5e3038f0Sstefano_zampini       }
236*5e3038f0Sstefano_zampini       for (i=0,sti=0;i<nc;i++) {
237*5e3038f0Sstefano_zampini         PetscInt n = lc[i]/lcb[i];
238*5e3038f0Sstefano_zampini 
239*5e3038f0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr);
240*5e3038f0Sstefano_zampini         sti  += n;
241*5e3038f0Sstefano_zampini       }
242*5e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
243*5e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
244*5e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
245*5e3038f0Sstefano_zampini     }
246*5e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
247*5e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
248*5e3038f0Sstefano_zampini   }
249*5e3038f0Sstefano_zampini 
250*5e3038f0Sstefano_zampini   /* Free workspace */
251*5e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
252*5e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
253*5e3038f0Sstefano_zampini   }
254*5e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
255*5e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
256*5e3038f0Sstefano_zampini   }
257*5e3038f0Sstefano_zampini   ierr = PetscFree4(lr,lc,lrb,lcb);CHKERRQ(ierr);
258*5e3038f0Sstefano_zampini   ierr = PetscFree5(isrow,iscol,islrow,islcol,snest);CHKERRQ(ierr);
259*5e3038f0Sstefano_zampini 
260*5e3038f0Sstefano_zampini   /* Create local matrix in MATNEST format */
261*5e3038f0Sstefano_zampini   convert = PETSC_FALSE;
262*5e3038f0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
263*5e3038f0Sstefano_zampini   if (convert) {
264*5e3038f0Sstefano_zampini     Mat M;
265*5e3038f0Sstefano_zampini 
266*5e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
267*5e3038f0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
268*5e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
269*5e3038f0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
270*5e3038f0Sstefano_zampini   }
271*5e3038f0Sstefano_zampini 
272*5e3038f0Sstefano_zampini   PetscFunctionReturn(0);
273*5e3038f0Sstefano_zampini }
274*5e3038f0Sstefano_zampini 
275*5e3038f0Sstefano_zampini #undef __FUNCT__
276d7f69cd0SStefano Zampini #define __FUNCT__ "MatTranspose_IS"
277d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
278d7f69cd0SStefano Zampini {
279d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
280d7f69cd0SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
281d7f69cd0SStefano Zampini   PetscBool              notset = PETSC_FALSE,cong = PETSC_TRUE;
282d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
283d7f69cd0SStefano Zampini 
284d7f69cd0SStefano Zampini   PetscFunctionBegin;
285d7f69cd0SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
286d7f69cd0SStefano Zampini     PetscBool rcong,ccong;
287d7f69cd0SStefano Zampini 
288d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr);
289d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr);
290fa520230SStefano Zampini     cong = (PetscBool)(rcong || ccong);
291d7f69cd0SStefano Zampini   }
292d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) {
293d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
294d7f69cd0SStefano Zampini   } else {
295d7f69cd0SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,&notset);CHKERRQ(ierr);
296d7f69cd0SStefano Zampini     C = *B;
297d7f69cd0SStefano Zampini   }
298d7f69cd0SStefano Zampini 
299d7f69cd0SStefano Zampini   if (!notset) {
300d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
301d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
302d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
303d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
304d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
305d7f69cd0SStefano Zampini   }
306d7f69cd0SStefano Zampini 
307d7f69cd0SStefano Zampini   /* perform local transposition */
308d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
309d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
310d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
311d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
312d7f69cd0SStefano Zampini 
313d7f69cd0SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
314d7f69cd0SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
315d7f69cd0SStefano Zampini 
316d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
317d7f69cd0SStefano Zampini     if (!cong) {
318d7f69cd0SStefano Zampini       ierr = MatDestroy(B);CHKERRQ(ierr);
319d7f69cd0SStefano Zampini     }
320d7f69cd0SStefano Zampini     *B = C;
321d7f69cd0SStefano Zampini   } else {
322d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
323d7f69cd0SStefano Zampini   }
324d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
325d7f69cd0SStefano Zampini }
326d7f69cd0SStefano Zampini 
327d7f69cd0SStefano Zampini #undef __FUNCT__
3283fd1c9e7SStefano Zampini #define __FUNCT__ "MatDiagonalSet_IS"
3293fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
3303fd1c9e7SStefano Zampini {
3313fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
3323fd1c9e7SStefano Zampini   PetscErrorCode ierr;
3333fd1c9e7SStefano Zampini 
3343fd1c9e7SStefano Zampini   PetscFunctionBegin;
3353fd1c9e7SStefano Zampini   if (!D) { /* this code branch is used by MatShift_IS */
3363fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
3373fd1c9e7SStefano Zampini   } else {
3383fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3393fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3403fd1c9e7SStefano Zampini   }
3413fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
3423fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
3433fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
3443fd1c9e7SStefano Zampini }
3453fd1c9e7SStefano Zampini 
3463fd1c9e7SStefano Zampini #undef __FUNCT__
3473fd1c9e7SStefano Zampini #define __FUNCT__ "MatShift_IS"
3483fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
3493fd1c9e7SStefano Zampini {
3503fd1c9e7SStefano Zampini   PetscErrorCode ierr;
3513fd1c9e7SStefano Zampini 
3523fd1c9e7SStefano Zampini   PetscFunctionBegin;
3533fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
3543fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
3553fd1c9e7SStefano Zampini }
3563fd1c9e7SStefano Zampini 
3573fd1c9e7SStefano Zampini #undef __FUNCT__
358f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS"
359f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
360f26d0771SStefano Zampini {
361f26d0771SStefano Zampini   PetscErrorCode ierr;
362f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
363f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
364f26d0771SStefano Zampini 
365f26d0771SStefano Zampini   PetscFunctionBegin;
366f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
367f26d0771SStefano 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);
368f26d0771SStefano Zampini #endif
369f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
370f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
371f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
372f26d0771SStefano Zampini   PetscFunctionReturn(0);
373f26d0771SStefano Zampini }
374f26d0771SStefano Zampini 
375f26d0771SStefano Zampini #undef __FUNCT__
376f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS"
377f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
378f26d0771SStefano Zampini {
379f26d0771SStefano Zampini   PetscErrorCode ierr;
380f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
381f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
382f26d0771SStefano Zampini 
383f26d0771SStefano Zampini   PetscFunctionBegin;
384f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
385f26d0771SStefano 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);
386f26d0771SStefano Zampini #endif
387f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
388f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
389f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
390f26d0771SStefano Zampini   PetscFunctionReturn(0);
391f26d0771SStefano Zampini }
392f26d0771SStefano Zampini 
393f26d0771SStefano Zampini #undef __FUNCT__
394a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private"
395f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
396a8116848SStefano Zampini {
397a8116848SStefano Zampini   PetscInt      *owners = map->range;
398a8116848SStefano Zampini   PetscInt       n      = map->n;
399a8116848SStefano Zampini   PetscSF        sf;
400a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
401a8116848SStefano Zampini   PetscSFNode   *ridxs;
402a8116848SStefano Zampini   PetscMPIInt    rank;
403a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
404a8116848SStefano Zampini   PetscErrorCode ierr;
405a8116848SStefano Zampini 
406a8116848SStefano Zampini   PetscFunctionBegin;
407a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
408a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
409a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
410a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
411a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
412a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
413a8116848SStefano Zampini     const PetscInt idx = idxs[r];
414a8116848SStefano 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);
415a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
416a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
417a8116848SStefano Zampini     }
418a8116848SStefano Zampini     ridxs[r].rank = p;
419a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
420a8116848SStefano Zampini   }
421a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
422a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
423a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
424a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
425f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
426a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
427f0ae7da4SStefano Zampini 
428f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
429a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
430a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
431a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
432a8116848SStefano Zampini     start -= cum;
433a8116848SStefano Zampini     cum = 0;
434a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
435a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
436a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
437a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
438a8116848SStefano Zampini   }
439a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
440a8116848SStefano Zampini   /* Compress and put in indices */
441a8116848SStefano Zampini   for (r = 0; r < n; ++r)
442a8116848SStefano Zampini     if (lidxs[r] >= 0) {
443a8116848SStefano Zampini       if (work) work[len] = work[r];
444a8116848SStefano Zampini       lidxs[len++] = r;
445a8116848SStefano Zampini     }
446a8116848SStefano Zampini   if (on) *on = len;
447a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
448a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
449a8116848SStefano Zampini   PetscFunctionReturn(0);
450a8116848SStefano Zampini }
451a8116848SStefano Zampini 
452a8116848SStefano Zampini #undef __FUNCT__
453a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS"
454a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
455a8116848SStefano Zampini {
456a8116848SStefano Zampini   Mat               locmat,newlocmat;
457a8116848SStefano Zampini   Mat_IS            *newmatis;
458a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
459a8116848SStefano Zampini   Vec               rtest,ltest;
460a8116848SStefano Zampini   const PetscScalar *array;
461a8116848SStefano Zampini #endif
462a8116848SStefano Zampini   const PetscInt    *idxs;
463a8116848SStefano Zampini   PetscInt          i,m,n;
464a8116848SStefano Zampini   PetscErrorCode    ierr;
465a8116848SStefano Zampini 
466a8116848SStefano Zampini   PetscFunctionBegin;
467a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
468a8116848SStefano Zampini     PetscBool ismatis;
469a8116848SStefano Zampini 
470a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
471a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
472a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
473a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
474a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
475a8116848SStefano Zampini   }
476a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
477a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
478a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
479a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
480a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
481a8116848SStefano Zampini   for (i=0;i<n;i++) {
482a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
483a8116848SStefano Zampini   }
484a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
485a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
486a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
487a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
488a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
489fd479f66SMatthew 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]));
490a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
491a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
492a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
493a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
494a8116848SStefano Zampini   for (i=0;i<n;i++) {
495a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
496a8116848SStefano Zampini   }
497a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
498a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
499a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
500a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
501a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
502fd479f66SMatthew 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]));
503a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
504a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
505a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
506a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
507a8116848SStefano Zampini #endif
508a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
509a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
510a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
511a8116848SStefano Zampini     IS                     is;
512a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
5136dd40735SStefano Zampini     PetscInt               ll,newloc;
514a8116848SStefano Zampini     MPI_Comm               comm;
515a8116848SStefano Zampini 
516a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
517a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
518a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
519a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
520a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
521a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
522a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
523a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
524f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
525a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
526a8116848SStefano Zampini     if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
527a8116848SStefano Zampini       ierr = MatISComputeSF_Private(mat);CHKERRQ(ierr);
528a8116848SStefano Zampini     }
529a8116848SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
530a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
531a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
532a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
533a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
534a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
535a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
536a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
537a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
538a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++)
539a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
540a8116848SStefano Zampini         lidxs[newloc] = i;
541a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
542a8116848SStefano Zampini       }
543a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
544a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
545a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
546a8116848SStefano Zampini     /* local is to extract local submatrix */
547a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
548a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
549a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
550a8116848SStefano Zampini       PetscBool cong;
551a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
552a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
553a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
554a8116848SStefano Zampini     }
555a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
556a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
557a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
558a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
559a8116848SStefano Zampini     } else {
560a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
561a8116848SStefano Zampini 
562a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
563a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
564f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
565a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
566a8116848SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
567a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
568a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
569a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
570a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
571a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
572a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
573a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
574a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
575a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++)
576a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
577a8116848SStefano Zampini           lidxs[newloc] = i;
578a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
579a8116848SStefano Zampini         }
580a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
581a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
582a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
583a8116848SStefano Zampini       /* local is to extract local submatrix */
584a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
585a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
586a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
587a8116848SStefano Zampini     }
588a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
589a8116848SStefano Zampini   } else {
590a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
591a8116848SStefano Zampini   }
592a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
593a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
594a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
595a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
596a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
597a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
598a8116848SStefano Zampini   }
599a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
600a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
601a8116848SStefano Zampini   PetscFunctionReturn(0);
602a8116848SStefano Zampini }
603a8116848SStefano Zampini 
604a8116848SStefano Zampini #undef __FUNCT__
6052b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS"
606a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
6072b404112SStefano Zampini {
6082b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
6092b404112SStefano Zampini   PetscBool      ismatis;
6102b404112SStefano Zampini   PetscErrorCode ierr;
6112b404112SStefano Zampini 
6122b404112SStefano Zampini   PetscFunctionBegin;
6132b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
6142b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
6152b404112SStefano Zampini   b = (Mat_IS*)B->data;
6162b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
6172b404112SStefano Zampini   PetscFunctionReturn(0);
6182b404112SStefano Zampini }
6192b404112SStefano Zampini 
6202b404112SStefano Zampini #undef __FUNCT__
6216bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS"
622a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
6236bd84002SStefano Zampini {
624527b2640SStefano Zampini   Vec               v;
625527b2640SStefano Zampini   const PetscScalar *array;
626527b2640SStefano Zampini   PetscInt          i,n;
6276bd84002SStefano Zampini   PetscErrorCode    ierr;
6286bd84002SStefano Zampini 
6296bd84002SStefano Zampini   PetscFunctionBegin;
630527b2640SStefano Zampini   *missing = PETSC_FALSE;
631527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
632527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
633527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
634527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
635527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
636527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
637527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
638527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
639527b2640SStefano Zampini   if (d) {
640527b2640SStefano Zampini     *d = -1;
641527b2640SStefano Zampini     if (*missing) {
642527b2640SStefano Zampini       PetscInt rstart;
643527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
644527b2640SStefano Zampini       *d = i+rstart;
645527b2640SStefano Zampini     }
646527b2640SStefano Zampini   }
6476bd84002SStefano Zampini   PetscFunctionReturn(0);
6486bd84002SStefano Zampini }
6496bd84002SStefano Zampini 
6506bd84002SStefano Zampini #undef __FUNCT__
65128f4e0baSStefano Zampini #define __FUNCT__ "MatISComputeSF_Private"
652a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat B)
65328f4e0baSStefano Zampini {
65428f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
65528f4e0baSStefano Zampini   const PetscInt *gidxs;
65628f4e0baSStefano Zampini   PetscErrorCode ierr;
65728f4e0baSStefano Zampini 
65828f4e0baSStefano Zampini   PetscFunctionBegin;
65928f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,&matis->sf_nleaves,NULL);CHKERRQ(ierr);
66028f4e0baSStefano Zampini   ierr = MatGetLocalSize(B,&matis->sf_nroots,NULL);CHKERRQ(ierr);
66128f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
6623bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
66328f4e0baSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,matis->sf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
6643bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
66528f4e0baSStefano Zampini   ierr = PetscMalloc2(matis->sf_nroots,&matis->sf_rootdata,matis->sf_nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
666a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
667a8116848SStefano Zampini     ierr = MatGetSize(matis->A,NULL,&matis->csf_nleaves);CHKERRQ(ierr);
668a8116848SStefano Zampini     ierr = MatGetLocalSize(B,NULL,&matis->csf_nroots);CHKERRQ(ierr);
669a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
670a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
671a8116848SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,matis->csf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
672a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
673a8116848SStefano Zampini     ierr = PetscMalloc2(matis->csf_nroots,&matis->csf_rootdata,matis->csf_nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
674a8116848SStefano Zampini   } else {
675a8116848SStefano Zampini     matis->csf = matis->sf;
676a8116848SStefano Zampini     matis->csf_nleaves = matis->sf_nleaves;
677a8116848SStefano Zampini     matis->csf_nroots = matis->sf_nroots;
678a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
679a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
680a8116848SStefano Zampini   }
68128f4e0baSStefano Zampini   PetscFunctionReturn(0);
68228f4e0baSStefano Zampini }
6832e1947a5SStefano Zampini 
6842e1947a5SStefano Zampini #undef __FUNCT__
6852e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
686eb82efa4SStefano Zampini /*@
687a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
688a88811baSStefano Zampini 
689a88811baSStefano Zampini    Collective on MPI_Comm
690a88811baSStefano Zampini 
691a88811baSStefano Zampini    Input Parameters:
692a88811baSStefano Zampini +  B - the matrix
693a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
694a88811baSStefano Zampini            (same value is used for all local rows)
695a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
696a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
697a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
698a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
699a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
700a88811baSStefano Zampini            the diagonal entry even if it is zero.
701a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
702a88811baSStefano Zampini            submatrix (same value is used for all local rows).
703a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
704a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
705a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
706a88811baSStefano Zampini            structure. The size of this array is equal to the number
707a88811baSStefano Zampini            of local rows, i.e 'm'.
708a88811baSStefano Zampini 
709a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
710a88811baSStefano Zampini 
711a88811baSStefano Zampini    Level: intermediate
712a88811baSStefano Zampini 
713a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
714a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
715a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
716a88811baSStefano Zampini 
717a88811baSStefano Zampini .keywords: matrix
718a88811baSStefano Zampini 
7193c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
720a88811baSStefano Zampini @*/
7212e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
7222e1947a5SStefano Zampini {
7232e1947a5SStefano Zampini   PetscErrorCode ierr;
7242e1947a5SStefano Zampini 
7252e1947a5SStefano Zampini   PetscFunctionBegin;
7262e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
7272e1947a5SStefano Zampini   PetscValidType(B,1);
7282e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
7292e1947a5SStefano Zampini   PetscFunctionReturn(0);
7302e1947a5SStefano Zampini }
7312e1947a5SStefano Zampini 
7322e1947a5SStefano Zampini #undef __FUNCT__
7332e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
7347230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
7352e1947a5SStefano Zampini {
7362e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
73728f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
7382e1947a5SStefano Zampini   PetscErrorCode ierr;
7392e1947a5SStefano Zampini 
7402e1947a5SStefano Zampini   PetscFunctionBegin;
7416c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
74228f4e0baSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
74328f4e0baSStefano Zampini     ierr = MatISComputeSF_Private(B);CHKERRQ(ierr);
74428f4e0baSStefano Zampini   }
7452e1947a5SStefano Zampini   if (!d_nnz) {
74628f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nz;
7472e1947a5SStefano Zampini   } else {
74828f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
7492e1947a5SStefano Zampini   }
7502e1947a5SStefano Zampini   if (!o_nnz) {
75128f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nz;
7522e1947a5SStefano Zampini   } else {
75328f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
7542e1947a5SStefano Zampini   }
75528f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
75628f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
75728f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
75828f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
75928f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves;i++) {
76028f4e0baSStefano Zampini     matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
7612e1947a5SStefano Zampini   }
76228f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
76328f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
76428f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
7652e1947a5SStefano Zampini   }
76628f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
76728f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
76828f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
7692e1947a5SStefano Zampini   }
77028f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
7712e1947a5SStefano Zampini   PetscFunctionReturn(0);
7722e1947a5SStefano Zampini }
773b4319ba4SBarry Smith 
774b4319ba4SBarry Smith #undef __FUNCT__
7753927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
7763927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
7773927de2eSStefano Zampini {
7783927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
7793927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
780ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
7813927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
7823927de2eSStefano Zampini   PetscInt        lrows,lcols;
7833927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
7843927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
7853927de2eSStefano Zampini   PetscBool       isdense,issbaij;
7863927de2eSStefano Zampini   PetscErrorCode  ierr;
7873927de2eSStefano Zampini 
7883927de2eSStefano Zampini   PetscFunctionBegin;
7893927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
7903927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
7913927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
7923927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
7933927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
7943927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
795ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
796ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
7977230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
798ecf5a873SStefano Zampini   } else {
799ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
800ecf5a873SStefano Zampini   }
801ecf5a873SStefano Zampini 
8023927de2eSStefano Zampini   if (issbaij) {
8033927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
8043927de2eSStefano Zampini   }
8053927de2eSStefano Zampini   /*
806ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
8073927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
8083927de2eSStefano Zampini   */
8093927de2eSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
8103927de2eSStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
8113927de2eSStefano Zampini   }
8123927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
8133927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
8143927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
8153927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
8163927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
8173927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
8183927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
8193927de2eSStefano Zampini       row_ownership[j] = i;
8203927de2eSStefano Zampini     }
8213927de2eSStefano Zampini   }
8227230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
8233927de2eSStefano Zampini 
8243927de2eSStefano Zampini   /*
8253927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
8263927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
8273927de2eSStefano Zampini   */
8283927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
8293927de2eSStefano Zampini   /* preallocation as a MATAIJ */
8303927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
8313927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
832ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
8333927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
8343927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
835ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
8363927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
8373927de2eSStefano Zampini           my_dnz[i] += 1;
8383927de2eSStefano Zampini         } else { /* offdiag block */
8393927de2eSStefano Zampini           my_onz[i] += 1;
8403927de2eSStefano Zampini         }
8413927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
8423927de2eSStefano Zampini         if (i != j) {
8433927de2eSStefano Zampini           owner = row_ownership[index_col];
8443927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
8453927de2eSStefano Zampini             my_dnz[j] += 1;
8463927de2eSStefano Zampini           } else {
8473927de2eSStefano Zampini             my_onz[j] += 1;
8483927de2eSStefano Zampini           }
8493927de2eSStefano Zampini         }
8503927de2eSStefano Zampini       }
8513927de2eSStefano Zampini     }
852bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
853bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
854bb1015c3SStefano Zampini     PetscBool      done;
855bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
856bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
857bb1015c3SStefano Zampini     jptr = jj;
858bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
859bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
860bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
861bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
862bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
863bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
864bb1015c3SStefano Zampini           my_dnz[i] += 1;
865bb1015c3SStefano Zampini         } else { /* offdiag block */
866bb1015c3SStefano Zampini           my_onz[i] += 1;
867bb1015c3SStefano Zampini         }
868bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
869bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
870bb1015c3SStefano Zampini           owner = row_ownership[index_col];
871bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
872bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
873bb1015c3SStefano Zampini           } else {
874bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
875bb1015c3SStefano Zampini           }
876bb1015c3SStefano Zampini         }
877bb1015c3SStefano Zampini       }
878bb1015c3SStefano Zampini     }
879bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
880bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
881bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
8823927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
8833927de2eSStefano Zampini       const PetscInt *cols;
884ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
8853927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
8863927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
8873927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
888ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
8893927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
8903927de2eSStefano Zampini           my_dnz[i] += 1;
8913927de2eSStefano Zampini         } else { /* offdiag block */
8923927de2eSStefano Zampini           my_onz[i] += 1;
8933927de2eSStefano Zampini         }
8943927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
895d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
8963927de2eSStefano Zampini           owner = row_ownership[index_col];
8973927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
898d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
8993927de2eSStefano Zampini           } else {
900d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
9013927de2eSStefano Zampini           }
9023927de2eSStefano Zampini         }
9033927de2eSStefano Zampini       }
9043927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
9053927de2eSStefano Zampini     }
9063927de2eSStefano Zampini   }
907ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
908ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
9097230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
910ecf5a873SStefano Zampini   }
9113927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
912ecf5a873SStefano Zampini 
913ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
9143927de2eSStefano Zampini   if (maxreduce) {
9153927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
9163927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
917bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
9183927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
9193927de2eSStefano Zampini   } else {
9203927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
9213927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
922bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
9233927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
9243927de2eSStefano Zampini   }
9253927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
9263927de2eSStefano Zampini 
9273927de2eSStefano Zampini   /* Resize preallocation if overestimated */
9283927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
9293927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
9303927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
9313927de2eSStefano Zampini   }
9323927de2eSStefano Zampini   /* set preallocation */
9333927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
9343927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
9353927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
9363927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
9373927de2eSStefano Zampini   }
9383927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
9393927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
9403927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
9413927de2eSStefano Zampini   if (issbaij) {
9423927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
9433927de2eSStefano Zampini   }
9443927de2eSStefano Zampini   PetscFunctionReturn(0);
9453927de2eSStefano Zampini }
9463927de2eSStefano Zampini 
9473927de2eSStefano Zampini #undef __FUNCT__
948b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
9497230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
950b7ce53b6SStefano Zampini {
951b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
952d9a9e74cSStefano Zampini   Mat            local_mat;
953b7ce53b6SStefano Zampini   /* info on mat */
9543cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
955b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
956686e3a49SStefano Zampini   PetscBool      isdense,issbaij,isseqaij;
9577c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
958b7ce53b6SStefano Zampini   /* values insertion */
959b7ce53b6SStefano Zampini   PetscScalar    *array;
960b7ce53b6SStefano Zampini   /* work */
961b7ce53b6SStefano Zampini   PetscErrorCode ierr;
962b7ce53b6SStefano Zampini 
963b7ce53b6SStefano Zampini   PetscFunctionBegin;
964b7ce53b6SStefano Zampini   /* get info from mat */
9657c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
9667c03b4e8SStefano Zampini   if (nsubdomains == 1) {
9677c03b4e8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
9687c03b4e8SStefano Zampini       ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&(*M));CHKERRQ(ierr);
9697c03b4e8SStefano Zampini     } else {
9707c03b4e8SStefano Zampini       ierr = MatCopy(matis->A,*M,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
9717c03b4e8SStefano Zampini     }
9727c03b4e8SStefano Zampini     PetscFunctionReturn(0);
9737c03b4e8SStefano Zampini   }
974b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
975b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
9763cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
977b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
978b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
979686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
980b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
981b7ce53b6SStefano Zampini 
982b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
983b7ce53b6SStefano Zampini     MatType     new_mat_type;
9843927de2eSStefano Zampini     PetscBool   issbaij_red;
985b7ce53b6SStefano Zampini 
986b7ce53b6SStefano Zampini     /* determining new matrix type */
987b2566f29SBarry Smith     ierr = MPIU_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
988b7ce53b6SStefano Zampini     if (issbaij_red) {
989b7ce53b6SStefano Zampini       new_mat_type = MATSBAIJ;
990b7ce53b6SStefano Zampini     } else {
991b7ce53b6SStefano Zampini       if (bs>1) {
992b7ce53b6SStefano Zampini         new_mat_type = MATBAIJ;
993b7ce53b6SStefano Zampini       } else {
994b7ce53b6SStefano Zampini         new_mat_type = MATAIJ;
995b7ce53b6SStefano Zampini       }
996b7ce53b6SStefano Zampini     }
997b7ce53b6SStefano Zampini 
9983927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
9993cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
10003927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
10013927de2eSStefano Zampini     ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr);
10023927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1003b7ce53b6SStefano Zampini   } else {
10043cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1005b7ce53b6SStefano Zampini     /* some checks */
1006b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1007b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
10083cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
10096c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
10106c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
10116c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
10126c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
10136c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1014b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1015b7ce53b6SStefano Zampini   }
1016d9a9e74cSStefano Zampini 
1017d9a9e74cSStefano Zampini   if (issbaij) {
1018d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1019d9a9e74cSStefano Zampini   } else {
1020d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1021d9a9e74cSStefano Zampini     local_mat = matis->A;
1022d9a9e74cSStefano Zampini   }
1023686e3a49SStefano Zampini 
1024b7ce53b6SStefano Zampini   /* Set values */
1025ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1026b7ce53b6SStefano Zampini   if (isdense) { /* special case for dense local matrices */
1027ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
1028ecf5a873SStefano Zampini 
1029ecf5a873SStefano Zampini     if (local_rows != local_cols) {
1030ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
1031ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1032ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
1033ecf5a873SStefano Zampini     } else {
1034ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
1035ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1036ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
1037ecf5a873SStefano Zampini     }
1038b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1039d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
1040ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
1041d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
1042ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
1043ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
1044ecf5a873SStefano Zampini     } else {
1045ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
1046ecf5a873SStefano Zampini     }
1047686e3a49SStefano Zampini   } else if (isseqaij) {
1048ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1049686e3a49SStefano Zampini     PetscBool done;
1050686e3a49SStefano Zampini 
1051d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1052bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1053d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1054686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1055ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1056686e3a49SStefano Zampini     }
1057d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1058bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1059d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1060686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1061ecf5a873SStefano Zampini     PetscInt i;
1062c0962df8SStefano Zampini 
1063686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1064686e3a49SStefano Zampini       PetscInt       j;
1065ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1066686e3a49SStefano Zampini 
1067ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1068ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1069ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1070686e3a49SStefano Zampini     }
1071b7ce53b6SStefano Zampini   }
1072b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1073d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1074b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1075b7ce53b6SStefano Zampini   if (isdense) {
1076b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1077b7ce53b6SStefano Zampini   }
1078b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1079b7ce53b6SStefano Zampini }
1080b7ce53b6SStefano Zampini 
1081b7ce53b6SStefano Zampini #undef __FUNCT__
1082b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
1083b7ce53b6SStefano Zampini /*@
1084b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1085b7ce53b6SStefano Zampini 
1086b7ce53b6SStefano Zampini   Input Parameter:
1087b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1088b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1089b7ce53b6SStefano Zampini 
1090b7ce53b6SStefano Zampini   Output Parameter:
1091b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1092b7ce53b6SStefano Zampini 
1093b7ce53b6SStefano Zampini   Level: developer
1094b7ce53b6SStefano Zampini 
1095eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1096b7ce53b6SStefano Zampini 
1097b7ce53b6SStefano Zampini .seealso: MATIS
1098b7ce53b6SStefano Zampini @*/
1099b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1100b7ce53b6SStefano Zampini {
1101b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1102b7ce53b6SStefano Zampini 
1103b7ce53b6SStefano Zampini   PetscFunctionBegin;
1104b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1105b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1106b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1107b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1108b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1109b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
11106c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1111b7ce53b6SStefano Zampini   }
1112b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1113b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1114b7ce53b6SStefano Zampini }
1115b7ce53b6SStefano Zampini 
1116b7ce53b6SStefano Zampini #undef __FUNCT__
1117ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
1118ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1119ad6194a2SStefano Zampini {
1120ad6194a2SStefano Zampini   PetscErrorCode ierr;
1121ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1122ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1123ad6194a2SStefano Zampini   Mat            B,localmat;
1124ad6194a2SStefano Zampini 
1125ad6194a2SStefano Zampini   PetscFunctionBegin;
1126ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1127ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1128ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1129e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1130ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1131ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1132b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1133ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1134ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1135ad6194a2SStefano Zampini   *newmat = B;
1136ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1137ad6194a2SStefano Zampini }
1138ad6194a2SStefano Zampini 
1139ad6194a2SStefano Zampini #undef __FUNCT__
114069796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
1141a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
114269796d55SStefano Zampini {
114369796d55SStefano Zampini   PetscErrorCode ierr;
114469796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
114569796d55SStefano Zampini   PetscBool      local_sym;
114669796d55SStefano Zampini 
114769796d55SStefano Zampini   PetscFunctionBegin;
114869796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1149b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
115069796d55SStefano Zampini   PetscFunctionReturn(0);
115169796d55SStefano Zampini }
115269796d55SStefano Zampini 
115369796d55SStefano Zampini #undef __FUNCT__
115469796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
1155a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
115669796d55SStefano Zampini {
115769796d55SStefano Zampini   PetscErrorCode ierr;
115869796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
115969796d55SStefano Zampini   PetscBool      local_sym;
116069796d55SStefano Zampini 
116169796d55SStefano Zampini   PetscFunctionBegin;
116269796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1163b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
116469796d55SStefano Zampini   PetscFunctionReturn(0);
116569796d55SStefano Zampini }
116669796d55SStefano Zampini 
116769796d55SStefano Zampini #undef __FUNCT__
1168b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
1169a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1170b4319ba4SBarry Smith {
1171dfbe8321SBarry Smith   PetscErrorCode ierr;
1172b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1173b4319ba4SBarry Smith 
1174b4319ba4SBarry Smith   PetscFunctionBegin;
11756bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1176e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1177e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
11786bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
11796bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
11803fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1181a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1182a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1183a8116848SStefano Zampini   if (b->sf != b->csf) {
1184a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1185a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1186a8116848SStefano Zampini   }
118728f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
118828f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1189bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1190dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1191bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1192b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1193b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
11942e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1195b4319ba4SBarry Smith   PetscFunctionReturn(0);
1196b4319ba4SBarry Smith }
1197b4319ba4SBarry Smith 
1198b4319ba4SBarry Smith #undef __FUNCT__
1199b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
1200a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1201b4319ba4SBarry Smith {
1202dfbe8321SBarry Smith   PetscErrorCode ierr;
1203b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1204b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1205b4319ba4SBarry Smith 
1206b4319ba4SBarry Smith   PetscFunctionBegin;
1207b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1208e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1209e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1210b4319ba4SBarry Smith 
1211b4319ba4SBarry Smith   /* multiply the local matrix */
1212b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1213b4319ba4SBarry Smith 
1214b4319ba4SBarry Smith   /* scatter product back into global memory */
12152dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1216e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1217e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1218b4319ba4SBarry Smith   PetscFunctionReturn(0);
1219b4319ba4SBarry Smith }
1220b4319ba4SBarry Smith 
1221b4319ba4SBarry Smith #undef __FUNCT__
12222e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
1223a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
12242e74eeadSLisandro Dalcin {
1225650997f4SStefano Zampini   Vec            temp_vec;
12262e74eeadSLisandro Dalcin   PetscErrorCode ierr;
12272e74eeadSLisandro Dalcin 
12282e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1229650997f4SStefano Zampini   if (v3 != v2) {
1230650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1231650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1232650997f4SStefano Zampini   } else {
1233650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1234650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1235650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1236650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1237650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1238650997f4SStefano Zampini   }
12392e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
12402e74eeadSLisandro Dalcin }
12412e74eeadSLisandro Dalcin 
12422e74eeadSLisandro Dalcin #undef __FUNCT__
12432e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
1244a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
12452e74eeadSLisandro Dalcin {
12462e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
12472e74eeadSLisandro Dalcin   PetscErrorCode ierr;
12482e74eeadSLisandro Dalcin 
1249e176bc59SStefano Zampini   PetscFunctionBegin;
12502e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1251e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1252e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12532e74eeadSLisandro Dalcin 
12542e74eeadSLisandro Dalcin   /* multiply the local matrix */
1255e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
12562e74eeadSLisandro Dalcin 
12572e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1258e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1259e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1260e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12612e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
12622e74eeadSLisandro Dalcin }
12632e74eeadSLisandro Dalcin 
12642e74eeadSLisandro Dalcin #undef __FUNCT__
12652e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
1266a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
12672e74eeadSLisandro Dalcin {
1268650997f4SStefano Zampini   Vec            temp_vec;
12692e74eeadSLisandro Dalcin   PetscErrorCode ierr;
12702e74eeadSLisandro Dalcin 
12712e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1272650997f4SStefano Zampini   if (v3 != v2) {
1273650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1274650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1275650997f4SStefano Zampini   } else {
1276650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1277650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1278650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1279650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1280650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1281650997f4SStefano Zampini   }
12822e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
12832e74eeadSLisandro Dalcin }
12842e74eeadSLisandro Dalcin 
12852e74eeadSLisandro Dalcin #undef __FUNCT__
1286b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
1287a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1288b4319ba4SBarry Smith {
1289b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1290dfbe8321SBarry Smith   PetscErrorCode ierr;
1291b4319ba4SBarry Smith   PetscViewer    sviewer;
1292b4319ba4SBarry Smith 
1293b4319ba4SBarry Smith   PetscFunctionBegin;
12943f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1295b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
12963f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
12976e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1298b4319ba4SBarry Smith   PetscFunctionReturn(0);
1299b4319ba4SBarry Smith }
1300b4319ba4SBarry Smith 
1301b4319ba4SBarry Smith #undef __FUNCT__
1302b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
1303a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1304b4319ba4SBarry Smith {
1305dfbe8321SBarry Smith   PetscErrorCode ierr;
1306e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1307b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1308b4319ba4SBarry Smith   IS             from,to;
1309e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1310b4319ba4SBarry Smith 
1311b4319ba4SBarry Smith   PetscFunctionBegin;
1312784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1313e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
13143bbff08aSStefano Zampini   /* Destroy any previous data */
131570cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
131670cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
13173fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1318e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1319e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
13201c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
132128f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
132228f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
13233bbff08aSStefano Zampini 
13243bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1325fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1326fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1327fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1328fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1329b4319ba4SBarry Smith 
1330b4319ba4SBarry Smith   /* Create the local matrix A */
1331e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1332e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1333e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1334e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1335f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1336e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1337e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1338e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1339ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1340ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1341b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1342b4319ba4SBarry Smith 
1343f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1344b4319ba4SBarry Smith     /* Create the local work vectors */
13453bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1346b4319ba4SBarry Smith 
1347e176bc59SStefano Zampini     /* setup the global to local scatters */
1348e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1349e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1350784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1351e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1352e176bc59SStefano Zampini     if (rmapping != cmapping) {
1353e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1354e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1355e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1356e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1357e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1358e176bc59SStefano Zampini     } else {
1359e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1360e176bc59SStefano Zampini       is->cctx = is->rctx;
1361e176bc59SStefano Zampini     }
13623fd1c9e7SStefano Zampini 
13633fd1c9e7SStefano Zampini     /* interface counter vector (local) */
13643fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
13653fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
13663fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13673fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13683fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13693fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13703fd1c9e7SStefano Zampini 
13713fd1c9e7SStefano Zampini     /* free workspace */
1372e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1373e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
13746bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
13756bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1376f26d0771SStefano Zampini   }
137748ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1378b4319ba4SBarry Smith   PetscFunctionReturn(0);
1379b4319ba4SBarry Smith }
1380b4319ba4SBarry Smith 
13812e74eeadSLisandro Dalcin #undef __FUNCT__
13822e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
1383a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
13842e74eeadSLisandro Dalcin {
13852e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
13862e74eeadSLisandro Dalcin   PetscErrorCode ierr;
138797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
138897563a80SStefano Zampini   PetscInt       i,zm,zn;
138997563a80SStefano Zampini #endif
1390f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
13912e74eeadSLisandro Dalcin 
13922e74eeadSLisandro Dalcin   PetscFunctionBegin;
13932e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1394f26d0771SStefano 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);
139597563a80SStefano Zampini   /* count negative indices */
139697563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
139797563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
13982e74eeadSLisandro Dalcin #endif
139997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
140097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
140197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
140297563a80SStefano Zampini   /* count negative indices (should be the same as before) */
140397563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
140497563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
140597563a80SStefano 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");
140697563a80SStefano 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");
140797563a80SStefano Zampini #endif
14082e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
14092e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14102e74eeadSLisandro Dalcin }
14112e74eeadSLisandro Dalcin 
1412b4319ba4SBarry Smith #undef __FUNCT__
141397563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS"
1414a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
141597563a80SStefano Zampini {
141697563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
141797563a80SStefano Zampini   PetscErrorCode ierr;
141897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
141997563a80SStefano Zampini   PetscInt       i,zm,zn;
142097563a80SStefano Zampini #endif
1421f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
142297563a80SStefano Zampini 
142397563a80SStefano Zampini   PetscFunctionBegin;
142497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1425f26d0771SStefano 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);
142697563a80SStefano Zampini   /* count negative indices */
142797563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
142897563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
142997563a80SStefano Zampini #endif
143097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
143197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
143297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
143397563a80SStefano Zampini   /* count negative indices (should be the same as before) */
143497563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
143597563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
143697563a80SStefano 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");
143797563a80SStefano 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");
143897563a80SStefano Zampini #endif
143997563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
144097563a80SStefano Zampini   PetscFunctionReturn(0);
144197563a80SStefano Zampini }
144297563a80SStefano Zampini 
144397563a80SStefano Zampini #undef __FUNCT__
1444b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
1445a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1446b4319ba4SBarry Smith {
1447dfbe8321SBarry Smith   PetscErrorCode ierr;
1448b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1449b4319ba4SBarry Smith 
1450b4319ba4SBarry Smith   PetscFunctionBegin;
1451b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1452b4319ba4SBarry Smith   PetscFunctionReturn(0);
1453b4319ba4SBarry Smith }
1454b4319ba4SBarry Smith 
1455b4319ba4SBarry Smith #undef __FUNCT__
1456f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
1457a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1458f0006bf2SLisandro Dalcin {
1459f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1460f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1461f0006bf2SLisandro Dalcin 
1462f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1463f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1464f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1465f0006bf2SLisandro Dalcin }
1466f0006bf2SLisandro Dalcin 
1467f0006bf2SLisandro Dalcin #undef __FUNCT__
1468f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private"
1469f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1470f0ae7da4SStefano Zampini {
1471f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1472f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1473f0ae7da4SStefano Zampini 
1474f0ae7da4SStefano Zampini   PetscFunctionBegin;
1475f0ae7da4SStefano Zampini   if (!n) {
1476f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1477f0ae7da4SStefano Zampini   } else {
1478f0ae7da4SStefano Zampini     PetscInt i;
1479f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1480f0ae7da4SStefano Zampini 
1481f0ae7da4SStefano Zampini     if (columns) {
1482f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1483f0ae7da4SStefano Zampini     } else {
1484f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1485f0ae7da4SStefano Zampini     }
1486f0ae7da4SStefano Zampini     if (diag != 0.) {
1487f0ae7da4SStefano Zampini       const PetscScalar *array;
1488f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1489f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1490f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1491f0ae7da4SStefano Zampini       }
1492f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1493f0ae7da4SStefano Zampini     }
1494f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1495f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1496f0ae7da4SStefano Zampini   }
1497f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1498f0ae7da4SStefano Zampini }
1499f0ae7da4SStefano Zampini 
1500f0ae7da4SStefano Zampini #undef __FUNCT__
1501f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS"
1502f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
15032e74eeadSLisandro Dalcin {
15046e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
15056e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
15066e520ac8SStefano Zampini   PetscInt       *lrows;
15072e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15082e74eeadSLisandro Dalcin 
15092e74eeadSLisandro Dalcin   PetscFunctionBegin;
1510f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1511f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1512f0ae7da4SStefano Zampini     PetscBool cong;
1513f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1514f0ae7da4SStefano 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");
1515f0ae7da4SStefano 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");
1516f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1517f0ae7da4SStefano Zampini   }
1518f0ae7da4SStefano Zampini #endif
15196e520ac8SStefano Zampini   /* get locally owned rows */
1520f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
15216e520ac8SStefano Zampini   /* fix right hand side if needed */
15226e520ac8SStefano Zampini   if (x && b) {
15236e520ac8SStefano Zampini     const PetscScalar *xx;
15246e520ac8SStefano Zampini     PetscScalar       *bb;
15256e520ac8SStefano Zampini 
15266e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
15276e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
15286e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
15296e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
15306e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
15312e74eeadSLisandro Dalcin   }
15326e520ac8SStefano Zampini   /* get rows associated to the local matrices */
15336e520ac8SStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
15346e520ac8SStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
15356e520ac8SStefano Zampini   }
15366e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
15376e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
15386e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
15396e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
15406e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
15416e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
15426e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
15436e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
15446e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1545f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
15466e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
15472e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15482e74eeadSLisandro Dalcin }
15492e74eeadSLisandro Dalcin 
15502e74eeadSLisandro Dalcin #undef __FUNCT__
1551f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS"
1552f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1553b4319ba4SBarry Smith {
1554dfbe8321SBarry Smith   PetscErrorCode ierr;
1555b4319ba4SBarry Smith 
1556b4319ba4SBarry Smith   PetscFunctionBegin;
1557f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1558f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1559f0ae7da4SStefano Zampini }
15602205254eSKarl Rupp 
1561f0ae7da4SStefano Zampini #undef __FUNCT__
1562f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS"
1563f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1564f0ae7da4SStefano Zampini {
1565f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1566f0ae7da4SStefano Zampini 
1567f0ae7da4SStefano Zampini   PetscFunctionBegin;
1568f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1569b4319ba4SBarry Smith   PetscFunctionReturn(0);
1570b4319ba4SBarry Smith }
1571b4319ba4SBarry Smith 
1572b4319ba4SBarry Smith #undef __FUNCT__
1573b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
1574a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1575b4319ba4SBarry Smith {
1576b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1577dfbe8321SBarry Smith   PetscErrorCode ierr;
1578b4319ba4SBarry Smith 
1579b4319ba4SBarry Smith   PetscFunctionBegin;
1580b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1581b4319ba4SBarry Smith   PetscFunctionReturn(0);
1582b4319ba4SBarry Smith }
1583b4319ba4SBarry Smith 
1584b4319ba4SBarry Smith #undef __FUNCT__
1585b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
1586a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1587b4319ba4SBarry Smith {
1588b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1589dfbe8321SBarry Smith   PetscErrorCode ierr;
1590b4319ba4SBarry Smith 
1591b4319ba4SBarry Smith   PetscFunctionBegin;
1592b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1593b4319ba4SBarry Smith   PetscFunctionReturn(0);
1594b4319ba4SBarry Smith }
1595b4319ba4SBarry Smith 
1596b4319ba4SBarry Smith #undef __FUNCT__
1597b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
1598a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1599b4319ba4SBarry Smith {
1600b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1601b4319ba4SBarry Smith 
1602b4319ba4SBarry Smith   PetscFunctionBegin;
1603b4319ba4SBarry Smith   *local = is->A;
1604b4319ba4SBarry Smith   PetscFunctionReturn(0);
1605b4319ba4SBarry Smith }
1606b4319ba4SBarry Smith 
1607b4319ba4SBarry Smith #undef __FUNCT__
1608b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
1609b4319ba4SBarry Smith /*@
1610b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1611b4319ba4SBarry Smith 
1612b4319ba4SBarry Smith   Input Parameter:
1613b4319ba4SBarry Smith .  mat - the matrix
1614b4319ba4SBarry Smith 
1615b4319ba4SBarry Smith   Output Parameter:
1616eb82efa4SStefano Zampini .  local - the local matrix
1617b4319ba4SBarry Smith 
1618b4319ba4SBarry Smith   Level: advanced
1619b4319ba4SBarry Smith 
1620b4319ba4SBarry Smith   Notes:
1621b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1622b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1623b4319ba4SBarry Smith   of the MatSetValues() operation.
1624b4319ba4SBarry Smith 
1625b4319ba4SBarry Smith .seealso: MATIS
1626b4319ba4SBarry Smith @*/
16277087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1628b4319ba4SBarry Smith {
16294ac538c5SBarry Smith   PetscErrorCode ierr;
1630b4319ba4SBarry Smith 
1631b4319ba4SBarry Smith   PetscFunctionBegin;
16320700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1633b4319ba4SBarry Smith   PetscValidPointer(local,2);
16344ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1635b4319ba4SBarry Smith   PetscFunctionReturn(0);
1636b4319ba4SBarry Smith }
1637b4319ba4SBarry Smith 
16383b03a366Sstefano_zampini #undef __FUNCT__
16393b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
1640a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
16413b03a366Sstefano_zampini {
16423b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
16433b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
16443b03a366Sstefano_zampini   PetscErrorCode ierr;
16453b03a366Sstefano_zampini 
16463b03a366Sstefano_zampini   PetscFunctionBegin;
16474e4c7dbeSStefano Zampini   if (is->A) {
16483b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
16493b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1650f0ae7da4SStefano 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);
16514e4c7dbeSStefano Zampini   }
16523b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
16533b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
16543b03a366Sstefano_zampini   is->A = local;
16553b03a366Sstefano_zampini   PetscFunctionReturn(0);
16563b03a366Sstefano_zampini }
16573b03a366Sstefano_zampini 
16583b03a366Sstefano_zampini #undef __FUNCT__
16593b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
16603b03a366Sstefano_zampini /*@
1661eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
16623b03a366Sstefano_zampini 
16633b03a366Sstefano_zampini   Input Parameter:
16643b03a366Sstefano_zampini .  mat - the matrix
1665eb82efa4SStefano Zampini .  local - the local matrix
16663b03a366Sstefano_zampini 
16673b03a366Sstefano_zampini   Output Parameter:
16683b03a366Sstefano_zampini 
16693b03a366Sstefano_zampini   Level: advanced
16703b03a366Sstefano_zampini 
16713b03a366Sstefano_zampini   Notes:
16723b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
16733b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
16743b03a366Sstefano_zampini 
16753b03a366Sstefano_zampini .seealso: MATIS
16763b03a366Sstefano_zampini @*/
16773b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
16783b03a366Sstefano_zampini {
16793b03a366Sstefano_zampini   PetscErrorCode ierr;
16803b03a366Sstefano_zampini 
16813b03a366Sstefano_zampini   PetscFunctionBegin;
16823b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1683b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
16843b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
16853b03a366Sstefano_zampini   PetscFunctionReturn(0);
16863b03a366Sstefano_zampini }
16873b03a366Sstefano_zampini 
16886726f965SBarry Smith #undef __FUNCT__
16896726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
1690a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
16916726f965SBarry Smith {
16926726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
16936726f965SBarry Smith   PetscErrorCode ierr;
16946726f965SBarry Smith 
16956726f965SBarry Smith   PetscFunctionBegin;
16966726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
16976726f965SBarry Smith   PetscFunctionReturn(0);
16986726f965SBarry Smith }
16996726f965SBarry Smith 
17006726f965SBarry Smith #undef __FUNCT__
17012e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
1702a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
17032e74eeadSLisandro Dalcin {
17042e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
17052e74eeadSLisandro Dalcin   PetscErrorCode ierr;
17062e74eeadSLisandro Dalcin 
17072e74eeadSLisandro Dalcin   PetscFunctionBegin;
17082e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
17092e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
17102e74eeadSLisandro Dalcin }
17112e74eeadSLisandro Dalcin 
17122e74eeadSLisandro Dalcin #undef __FUNCT__
17132e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
1714a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
17152e74eeadSLisandro Dalcin {
17162e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
17172e74eeadSLisandro Dalcin   PetscErrorCode ierr;
17182e74eeadSLisandro Dalcin 
17192e74eeadSLisandro Dalcin   PetscFunctionBegin;
17202e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
1721e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
17222e74eeadSLisandro Dalcin 
17232e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
17242e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
1725e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1726e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17272e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
17282e74eeadSLisandro Dalcin }
17292e74eeadSLisandro Dalcin 
17302e74eeadSLisandro Dalcin #undef __FUNCT__
17316726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
1732a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
17336726f965SBarry Smith {
17346726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
17356726f965SBarry Smith   PetscErrorCode ierr;
17366726f965SBarry Smith 
17376726f965SBarry Smith   PetscFunctionBegin;
17384e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
17396726f965SBarry Smith   PetscFunctionReturn(0);
17406726f965SBarry Smith }
17416726f965SBarry Smith 
1742284134d9SBarry Smith #undef __FUNCT__
1743f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS"
1744f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
1745f26d0771SStefano Zampini {
1746f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
1747f26d0771SStefano Zampini   Mat_IS         *x;
1748f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1749f26d0771SStefano Zampini   PetscBool      ismatis;
1750f26d0771SStefano Zampini #endif
1751f26d0771SStefano Zampini   PetscErrorCode ierr;
1752f26d0771SStefano Zampini 
1753f26d0771SStefano Zampini   PetscFunctionBegin;
1754f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1755f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
1756f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
1757f26d0771SStefano Zampini #endif
1758f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
1759f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
1760f26d0771SStefano Zampini   PetscFunctionReturn(0);
1761f26d0771SStefano Zampini }
1762f26d0771SStefano Zampini 
1763f26d0771SStefano Zampini #undef __FUNCT__
1764f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS"
1765f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
1766f26d0771SStefano Zampini {
1767f26d0771SStefano Zampini   Mat                    lA;
1768f26d0771SStefano Zampini   Mat_IS                 *matis;
1769f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
1770f26d0771SStefano Zampini   IS                     is;
1771f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
1772f26d0771SStefano Zampini   PetscInt               nrg;
1773f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
1774f26d0771SStefano Zampini   PetscErrorCode         ierr;
1775f26d0771SStefano Zampini 
1776f26d0771SStefano Zampini   PetscFunctionBegin;
1777f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1778f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
1779f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
1780f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
1781f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1782f0ae7da4SStefano 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);
1783f26d0771SStefano Zampini #endif
1784f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
1785f26d0771SStefano Zampini   /* map from [0,nrl) to row */
1786f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
1787f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1788f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
1789f26d0771SStefano Zampini #else
1790f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
1791f26d0771SStefano Zampini #endif
1792f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
1793f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1794f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1795f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1796f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
1797f26d0771SStefano Zampini   /* compute new l2g map for columns */
1798f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
1799f26d0771SStefano Zampini     const PetscInt *cg,*cl;
1800f26d0771SStefano Zampini     PetscInt       ncg;
1801f26d0771SStefano Zampini     PetscInt       ncl;
1802f26d0771SStefano Zampini 
1803f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1804f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
1805f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
1806f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
1807f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1808f0ae7da4SStefano 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);
1809f26d0771SStefano Zampini #endif
1810f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
1811f26d0771SStefano Zampini     /* map from [0,ncl) to col */
1812f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
1813f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1814f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
1815f26d0771SStefano Zampini #else
1816f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
1817f26d0771SStefano Zampini #endif
1818f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
1819f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1820f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1821f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1822f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1823f26d0771SStefano Zampini   } else {
1824f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
1825f26d0771SStefano Zampini     cl2g = rl2g;
1826f26d0771SStefano Zampini   }
1827f26d0771SStefano Zampini   /* create the MATIS submatrix */
1828f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
1829f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
1830f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1831f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
1832b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
1833f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
1834f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
1835f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1836f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
1837f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
1838f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1839f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1840f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1841f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1842f26d0771SStefano Zampini   /* remove unsupported ops */
1843f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1844f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
1845f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
1846f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
1847f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
1848f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
1849f26d0771SStefano Zampini   PetscFunctionReturn(0);
1850f26d0771SStefano Zampini }
1851f26d0771SStefano Zampini 
1852f26d0771SStefano Zampini #undef __FUNCT__
1853284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
1854284134d9SBarry Smith /*@
18553c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
1856284134d9SBarry Smith        process but not across processes.
1857284134d9SBarry Smith 
1858284134d9SBarry Smith    Input Parameters:
1859284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
1860e176bc59SStefano Zampini .     bs      - block size of the matrix
1861df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
1862e176bc59SStefano Zampini .     rmap    - local to global map for rows
1863e176bc59SStefano Zampini -     cmap    - local to global map for cols
1864284134d9SBarry Smith 
1865284134d9SBarry Smith    Output Parameter:
1866284134d9SBarry Smith .    A - the resulting matrix
1867284134d9SBarry Smith 
18688e6c10adSSatish Balay    Level: advanced
18698e6c10adSSatish Balay 
18703c212e90SHong Zhang    Notes: See MATIS for more details.
18716fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
18726fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
18733c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
1874284134d9SBarry Smith 
1875284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
1876284134d9SBarry Smith @*/
1877e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
1878284134d9SBarry Smith {
1879284134d9SBarry Smith   PetscErrorCode ierr;
1880284134d9SBarry Smith 
1881284134d9SBarry Smith   PetscFunctionBegin;
18826fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
1883284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
18846fdf41d1SStefano Zampini   if (bs > 0) {
1885d3ee2243SStefano Zampini     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
18866fdf41d1SStefano Zampini   }
1887284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
1888284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
1889e176bc59SStefano Zampini   if (rmap && cmap) {
1890e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
1891e176bc59SStefano Zampini   } else if (!rmap) {
1892e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
1893e176bc59SStefano Zampini   } else {
1894e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
1895e176bc59SStefano Zampini   }
1896284134d9SBarry Smith   PetscFunctionReturn(0);
1897284134d9SBarry Smith }
1898284134d9SBarry Smith 
1899b4319ba4SBarry Smith /*MC
1900f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
1901b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
1902b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
1903b4319ba4SBarry Smith    product is handled "implicitly".
1904b4319ba4SBarry Smith 
1905b4319ba4SBarry Smith    Operations Provided:
19066726f965SBarry Smith +  MatMult()
19072e74eeadSLisandro Dalcin .  MatMultAdd()
19082e74eeadSLisandro Dalcin .  MatMultTranspose()
19092e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
19106726f965SBarry Smith .  MatZeroEntries()
19116726f965SBarry Smith .  MatSetOption()
19122e74eeadSLisandro Dalcin .  MatZeroRows()
19132e74eeadSLisandro Dalcin .  MatSetValues()
191497563a80SStefano Zampini .  MatSetValuesBlocked()
19156726f965SBarry Smith .  MatSetValuesLocal()
191697563a80SStefano Zampini .  MatSetValuesBlockedLocal()
19172e74eeadSLisandro Dalcin .  MatScale()
19182e74eeadSLisandro Dalcin .  MatGetDiagonal()
19192b404112SStefano Zampini .  MatMissingDiagonal()
19202b404112SStefano Zampini .  MatDuplicate()
19212b404112SStefano Zampini .  MatCopy()
1922f26d0771SStefano Zampini .  MatAXPY()
1923f26d0771SStefano Zampini .  MatGetSubMatrix()
1924f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
1925d7f69cd0SStefano Zampini .  MatTranspose()
19266726f965SBarry Smith -  MatSetLocalToGlobalMapping()
1927b4319ba4SBarry Smith 
1928b4319ba4SBarry Smith    Options Database Keys:
1929b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
1930b4319ba4SBarry Smith 
1931b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
1932b4319ba4SBarry Smith 
1933b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
1934b4319ba4SBarry Smith 
1935b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
1936eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
1937b4319ba4SBarry Smith 
1938b4319ba4SBarry Smith   Level: advanced
1939b4319ba4SBarry Smith 
1940f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
1941b4319ba4SBarry Smith 
1942b4319ba4SBarry Smith M*/
1943b4319ba4SBarry Smith 
1944b4319ba4SBarry Smith #undef __FUNCT__
1945b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
19468cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
1947b4319ba4SBarry Smith {
1948dfbe8321SBarry Smith   PetscErrorCode ierr;
1949b4319ba4SBarry Smith   Mat_IS         *b;
1950b4319ba4SBarry Smith 
1951b4319ba4SBarry Smith   PetscFunctionBegin;
1952b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
1953b4319ba4SBarry Smith   A->data = (void*)b;
1954b4319ba4SBarry Smith 
1955e176bc59SStefano Zampini   /* matrix ops */
1956e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1957b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
19582e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
19592e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
19602e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
1961b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
1962b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
19632e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
196498921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
1965b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
1966f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
19672e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
1968f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
1969b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
1970b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
1971b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
19726726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
19732e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
19742e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
19756726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
197669796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
197769796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
1978ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
19796bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
19802b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
1981659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
1982a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
1983f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
19843fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
19853fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
1986d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
1987b4319ba4SBarry Smith 
1988b7ce53b6SStefano Zampini   /* special MATIS functions */
1989bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
1990bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
1991b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
19922e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
199317667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
1994b4319ba4SBarry Smith   PetscFunctionReturn(0);
1995b4319ba4SBarry Smith }
1996