xref: /petsc/src/mat/impls/is/matis.c (revision 75d48cdbf3d989106dd25a7997baa36b63209129)
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*/
116989cf23SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
124f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h>
1328f4e0baSStefano Zampini 
14f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
15b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
16b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
17f26d0771SStefano Zampini 
18*75d48cdbSStefano Zampini static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr)
19*75d48cdbSStefano Zampini {
20*75d48cdbSStefano Zampini   MatISPtAP      ptap = (MatISPtAP)ptr;
21*75d48cdbSStefano Zampini   PetscErrorCode ierr;
22*75d48cdbSStefano Zampini 
23*75d48cdbSStefano Zampini   PetscFunctionBegin;
24*75d48cdbSStefano Zampini   ierr = MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP);CHKERRQ(ierr);
25*75d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis0);CHKERRQ(ierr);
26*75d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis1);CHKERRQ(ierr);
27*75d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris0);CHKERRQ(ierr);
28*75d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
29*75d48cdbSStefano Zampini   ierr = PetscFree(ptap);CHKERRQ(ierr);
30*75d48cdbSStefano Zampini   PetscFunctionReturn(0);
31*75d48cdbSStefano Zampini }
32*75d48cdbSStefano Zampini 
33*75d48cdbSStefano Zampini static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C)
34*75d48cdbSStefano Zampini {
35*75d48cdbSStefano Zampini   MatISPtAP      ptap;
36*75d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
37*75d48cdbSStefano Zampini   Mat            lA,lC;
38*75d48cdbSStefano Zampini   MatReuse       reuse;
39*75d48cdbSStefano Zampini   IS             ris[2],cis[2];
40*75d48cdbSStefano Zampini   PetscContainer c;
41*75d48cdbSStefano Zampini   PetscInt       n;
42*75d48cdbSStefano Zampini   PetscErrorCode ierr;
43*75d48cdbSStefano Zampini 
44*75d48cdbSStefano Zampini   PetscFunctionBegin;
45*75d48cdbSStefano Zampini   ierr = PetscObjectQuery((PetscObject)(C),"_MatIS_PtAP",(PetscObject*)&c);CHKERRQ(ierr);
46*75d48cdbSStefano Zampini   if (!c) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information");
47*75d48cdbSStefano Zampini   ierr   = PetscContainerGetPointer(c,(void**)&ptap);CHKERRQ(ierr);
48*75d48cdbSStefano Zampini   ris[0] = ptap->ris0;
49*75d48cdbSStefano Zampini   ris[1] = ptap->ris1;
50*75d48cdbSStefano Zampini   cis[0] = ptap->cis0;
51*75d48cdbSStefano Zampini   cis[1] = ptap->cis1;
52*75d48cdbSStefano Zampini   n      = ptap->ris1 ? 2 : 1;
53*75d48cdbSStefano Zampini   reuse  = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX;
54*75d48cdbSStefano Zampini   ierr   = MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP);CHKERRQ(ierr);
55*75d48cdbSStefano Zampini 
56*75d48cdbSStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
57*75d48cdbSStefano Zampini   ierr = MatISGetLocalMat(C,&lC);CHKERRQ(ierr);
58*75d48cdbSStefano Zampini   if (ptap->ris1) { /* unsymmetric A mapping */
59*75d48cdbSStefano Zampini     Mat lPt;
60*75d48cdbSStefano Zampini 
61*75d48cdbSStefano Zampini     ierr = MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt);CHKERRQ(ierr);
62*75d48cdbSStefano Zampini     ierr = MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
63*75d48cdbSStefano Zampini     if (matis->storel2l) {
64*75d48cdbSStefano Zampini       ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt);CHKERRQ(ierr);
65*75d48cdbSStefano Zampini     }
66*75d48cdbSStefano Zampini     ierr = MatDestroy(&lPt);CHKERRQ(ierr);
67*75d48cdbSStefano Zampini   } else {
68*75d48cdbSStefano Zampini     ierr = MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
69*75d48cdbSStefano Zampini     if (matis->storel2l) {
70*75d48cdbSStefano Zampini      ierr = PetscObjectCompose((PetscObject)(C),"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0]);CHKERRQ(ierr);
71*75d48cdbSStefano Zampini     }
72*75d48cdbSStefano Zampini   }
73*75d48cdbSStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
74*75d48cdbSStefano Zampini     ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
75*75d48cdbSStefano Zampini     ierr = MatDestroy(&lC);CHKERRQ(ierr);
76*75d48cdbSStefano Zampini   }
77*75d48cdbSStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
78*75d48cdbSStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
79*75d48cdbSStefano Zampini   PetscFunctionReturn(0);
80*75d48cdbSStefano Zampini }
81*75d48cdbSStefano Zampini 
82*75d48cdbSStefano Zampini static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT,IS *cis)
83*75d48cdbSStefano Zampini {
84*75d48cdbSStefano Zampini   Mat            Po,Pd;
85*75d48cdbSStefano Zampini   IS             zd,zo;
86*75d48cdbSStefano Zampini   const PetscInt *garray;
87*75d48cdbSStefano Zampini   PetscInt       *aux,i,bs;
88*75d48cdbSStefano Zampini   PetscInt       dc,stc,oc,ctd,cto;
89*75d48cdbSStefano Zampini   PetscBool      ismpiaij,ismpibaij,isseqaij,isseqbaij;
90*75d48cdbSStefano Zampini   MPI_Comm       comm;
91*75d48cdbSStefano Zampini   PetscErrorCode ierr;
92*75d48cdbSStefano Zampini 
93*75d48cdbSStefano Zampini   PetscFunctionBegin;
94*75d48cdbSStefano Zampini   PetscValidHeaderSpecific(PT,MAT_CLASSID,1);
95*75d48cdbSStefano Zampini   PetscValidPointer(cis,2);
96*75d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)PT,&comm);CHKERRQ(ierr);
97*75d48cdbSStefano Zampini   bs   = 1;
98*75d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
99*75d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
100*75d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
101*75d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
102*75d48cdbSStefano Zampini   if (isseqaij || isseqbaij) {
103*75d48cdbSStefano Zampini     Pd = PT;
104*75d48cdbSStefano Zampini     Po = NULL;
105*75d48cdbSStefano Zampini     garray = NULL;
106*75d48cdbSStefano Zampini   } else if (ismpiaij) {
107*75d48cdbSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
108*75d48cdbSStefano Zampini   } else if (ismpibaij) {
109*75d48cdbSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
110*75d48cdbSStefano Zampini     ierr = MatGetBlockSize(PT,&bs);CHKERRQ(ierr);
111*75d48cdbSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(PT))->type_name);
112*75d48cdbSStefano Zampini 
113*75d48cdbSStefano Zampini   /* identify any null columns in Pd or Po */
114*75d48cdbSStefano Zampini   zo = zd = NULL;
115*75d48cdbSStefano Zampini   if (Po) {
116*75d48cdbSStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,&zo);CHKERRQ(ierr);
117*75d48cdbSStefano Zampini   }
118*75d48cdbSStefano Zampini   ierr = MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,&zd);CHKERRQ(ierr);
119*75d48cdbSStefano Zampini 
120*75d48cdbSStefano Zampini   ierr = MatGetLocalSize(PT,NULL,&dc);CHKERRQ(ierr);
121*75d48cdbSStefano Zampini   ierr = MatGetOwnershipRangeColumn(PT,&stc,NULL);CHKERRQ(ierr);
122*75d48cdbSStefano Zampini   if (Po) { ierr = MatGetLocalSize(Po,NULL,&oc);CHKERRQ(ierr); }
123*75d48cdbSStefano Zampini   else oc = 0;
124*75d48cdbSStefano Zampini   ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
125*75d48cdbSStefano Zampini   if (zd) {
126*75d48cdbSStefano Zampini     const PetscInt *idxs;
127*75d48cdbSStefano Zampini     PetscInt       nz;
128*75d48cdbSStefano Zampini 
129*75d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
130*75d48cdbSStefano Zampini     ierr = ISSetBlockSize(zd,bs);CHKERRQ(ierr);
131*75d48cdbSStefano Zampini     ierr = ISGetLocalSize(zd,&nz);CHKERRQ(ierr);
132*75d48cdbSStefano Zampini     ierr = ISGetIndices(zd,&idxs);CHKERRQ(ierr);
133*75d48cdbSStefano Zampini     ctd  = nz/bs;
134*75d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs;
135*75d48cdbSStefano Zampini     ierr = ISRestoreIndices(zd,&idxs);CHKERRQ(ierr);
136*75d48cdbSStefano Zampini   } else {
137*75d48cdbSStefano Zampini     ctd = dc/bs;
138*75d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = i+stc/bs;
139*75d48cdbSStefano Zampini   }
140*75d48cdbSStefano Zampini   if (zo) {
141*75d48cdbSStefano Zampini     const PetscInt *idxs;
142*75d48cdbSStefano Zampini     PetscInt       nz;
143*75d48cdbSStefano Zampini 
144*75d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
145*75d48cdbSStefano Zampini     ierr = ISSetBlockSize(zo,bs);CHKERRQ(ierr);
146*75d48cdbSStefano Zampini     ierr = ISGetLocalSize(zo,&nz);CHKERRQ(ierr);
147*75d48cdbSStefano Zampini     ierr = ISGetIndices(zo,&idxs);CHKERRQ(ierr);
148*75d48cdbSStefano Zampini     cto  = nz/bs;
149*75d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs];
150*75d48cdbSStefano Zampini     ierr = ISRestoreIndices(zo,&idxs);CHKERRQ(ierr);
151*75d48cdbSStefano Zampini   } else {
152*75d48cdbSStefano Zampini     cto = oc/bs;
153*75d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[i];
154*75d48cdbSStefano Zampini   }
155*75d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis);CHKERRQ(ierr);
156*75d48cdbSStefano Zampini   ierr = ISDestroy(&zd);CHKERRQ(ierr);
157*75d48cdbSStefano Zampini   ierr = ISDestroy(&zo);CHKERRQ(ierr);
158*75d48cdbSStefano Zampini   PetscFunctionReturn(0);
159*75d48cdbSStefano Zampini }
160*75d48cdbSStefano Zampini 
161*75d48cdbSStefano Zampini static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat *C)
162*75d48cdbSStefano Zampini {
163*75d48cdbSStefano Zampini   Mat                    PT;
164*75d48cdbSStefano Zampini   MatISPtAP              ptap;
165*75d48cdbSStefano Zampini   ISLocalToGlobalMapping Crl2g,Ccl2g,rl2g,cl2g;
166*75d48cdbSStefano Zampini   PetscContainer         c;
167*75d48cdbSStefano Zampini   const PetscInt         *garray;
168*75d48cdbSStefano Zampini   PetscInt               ibs,N,dc;
169*75d48cdbSStefano Zampini   MPI_Comm               comm;
170*75d48cdbSStefano Zampini   PetscErrorCode         ierr;
171*75d48cdbSStefano Zampini 
172*75d48cdbSStefano Zampini   PetscFunctionBegin;
173*75d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
174*75d48cdbSStefano Zampini   ierr = MatCreate(comm,C);CHKERRQ(ierr);
175*75d48cdbSStefano Zampini   ierr = MatSetType(*C,MATIS);CHKERRQ(ierr);
176*75d48cdbSStefano Zampini   ierr = MatGetSize(P,NULL,&N);CHKERRQ(ierr);
177*75d48cdbSStefano Zampini   ierr = MatGetLocalSize(P,NULL,&dc);CHKERRQ(ierr);
178*75d48cdbSStefano Zampini   ierr = MatSetSizes(*C,dc,dc,N,N);CHKERRQ(ierr);
179*75d48cdbSStefano Zampini /* Not sure about this
180*75d48cdbSStefano Zampini   ierr = MatGetBlockSizes(P,NULL,&ibs);CHKERRQ(ierr);
181*75d48cdbSStefano Zampini   ierr = MatSetBlockSize(*C,ibs);CHKERRQ(ierr);
182*75d48cdbSStefano Zampini */
183*75d48cdbSStefano Zampini 
184*75d48cdbSStefano Zampini   ierr = PetscNew(&ptap);CHKERRQ(ierr);
185*75d48cdbSStefano Zampini   ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
186*75d48cdbSStefano Zampini   ierr = PetscContainerSetPointer(c,ptap);CHKERRQ(ierr);
187*75d48cdbSStefano Zampini   ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyPtAP_Private);CHKERRQ(ierr);
188*75d48cdbSStefano Zampini   ierr = PetscObjectCompose((PetscObject)(*C),"_MatIS_PtAP",(PetscObject)c);CHKERRQ(ierr);
189*75d48cdbSStefano Zampini   ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
190*75d48cdbSStefano Zampini   ptap->fill = fill;
191*75d48cdbSStefano Zampini 
192*75d48cdbSStefano Zampini   ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
193*75d48cdbSStefano Zampini 
194*75d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&ibs);CHKERRQ(ierr);
195*75d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cl2g,&N);CHKERRQ(ierr);
196*75d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&garray);CHKERRQ(ierr);
197*75d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris0);CHKERRQ(ierr);
198*75d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&garray);CHKERRQ(ierr);
199*75d48cdbSStefano Zampini 
200*75d48cdbSStefano Zampini   ierr = MatCreateSubMatrix(P,ptap->ris0,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
201*75d48cdbSStefano Zampini   ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis0);CHKERRQ(ierr);
202*75d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(ptap->cis0,&Ccl2g);CHKERRQ(ierr);
203*75d48cdbSStefano Zampini   ierr = MatDestroy(&PT);CHKERRQ(ierr);
204*75d48cdbSStefano Zampini 
205*75d48cdbSStefano Zampini   Crl2g = NULL;
206*75d48cdbSStefano Zampini   if (rl2g != cl2g) { /* unsymmetric A mapping */
207*75d48cdbSStefano Zampini     PetscBool same,lsame = PETSC_FALSE;
208*75d48cdbSStefano Zampini     PetscInt  N1,ibs1;
209*75d48cdbSStefano Zampini 
210*75d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&N1);CHKERRQ(ierr);
211*75d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&ibs1);CHKERRQ(ierr);
212*75d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&garray);CHKERRQ(ierr);
213*75d48cdbSStefano Zampini     ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris1);CHKERRQ(ierr);
214*75d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&garray);CHKERRQ(ierr);
215*75d48cdbSStefano Zampini     if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */
216*75d48cdbSStefano Zampini       const PetscInt *i1,*i2;
217*75d48cdbSStefano Zampini 
218*75d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris0,&i1);CHKERRQ(ierr);
219*75d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris1,&i2);CHKERRQ(ierr);
220*75d48cdbSStefano Zampini       ierr = PetscMemcmp(i1,i2,N*sizeof(*i1),&lsame);CHKERRQ(ierr);
221*75d48cdbSStefano Zampini     }
222*75d48cdbSStefano Zampini     ierr = MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm);CHKERRQ(ierr);
223*75d48cdbSStefano Zampini     if (same) {
224*75d48cdbSStefano Zampini       ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
225*75d48cdbSStefano Zampini     } else {
226*75d48cdbSStefano Zampini       ierr = MatCreateSubMatrix(P,ptap->ris1,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
227*75d48cdbSStefano Zampini       ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis1);CHKERRQ(ierr);
228*75d48cdbSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(ptap->cis1,&Crl2g);CHKERRQ(ierr);
229*75d48cdbSStefano Zampini       ierr = MatDestroy(&PT);CHKERRQ(ierr);
230*75d48cdbSStefano Zampini     }
231*75d48cdbSStefano Zampini   }
232*75d48cdbSStefano Zampini /* Not sure about this
233*75d48cdbSStefano Zampini   if (!Crl2g) {
234*75d48cdbSStefano Zampini     ierr = MatGetBlockSize(*C,&ibs);CHKERRQ(ierr);
235*75d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs);CHKERRQ(ierr);
236*75d48cdbSStefano Zampini   }
237*75d48cdbSStefano Zampini */
238*75d48cdbSStefano Zampini   ierr = MatSetLocalToGlobalMapping(*C,Crl2g ? Crl2g : Ccl2g,Ccl2g);CHKERRQ(ierr);
239*75d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Crl2g);CHKERRQ(ierr);
240*75d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Ccl2g);CHKERRQ(ierr);
241*75d48cdbSStefano Zampini 
242*75d48cdbSStefano Zampini   (*C)->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ;
243*75d48cdbSStefano Zampini   PetscFunctionReturn(0);
244*75d48cdbSStefano Zampini }
245*75d48cdbSStefano Zampini 
246*75d48cdbSStefano Zampini PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
247*75d48cdbSStefano Zampini {
248*75d48cdbSStefano Zampini   PetscErrorCode ierr;
249*75d48cdbSStefano Zampini 
250*75d48cdbSStefano Zampini   PetscFunctionBegin;
251*75d48cdbSStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
252*75d48cdbSStefano Zampini     ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
253*75d48cdbSStefano Zampini     ierr = MatPtAPSymbolic_IS_XAIJ(A,P,fill,C);CHKERRQ(ierr);
254*75d48cdbSStefano Zampini     ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
255*75d48cdbSStefano Zampini   }
256*75d48cdbSStefano Zampini   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
257*75d48cdbSStefano Zampini   ierr = ((*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr);
258*75d48cdbSStefano Zampini   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
259*75d48cdbSStefano Zampini   PetscFunctionReturn(0);
260*75d48cdbSStefano Zampini }
261*75d48cdbSStefano Zampini 
2625b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
2635b003df0Sstefano_zampini {
2645b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
2655b003df0Sstefano_zampini   PetscInt         i;
2665b003df0Sstefano_zampini   PetscErrorCode   ierr;
2675b003df0Sstefano_zampini 
268ab4d48faSStefano Zampini   PetscFunctionBegin;
2695b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
2705b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
2715b003df0Sstefano_zampini   }
2725b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
2735b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
2745b003df0Sstefano_zampini   }
2755b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
2765b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
2775b003df0Sstefano_zampini   PetscFunctionReturn(0);
2785b003df0Sstefano_zampini }
279a72627d2SStefano Zampini 
2806989cf23SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
2816989cf23SStefano Zampini {
2826989cf23SStefano Zampini   Mat_MPIAIJ             *aij  = (Mat_MPIAIJ*)A->data;
2836989cf23SStefano Zampini   Mat_SeqAIJ             *diag = (Mat_SeqAIJ*)(aij->A->data);
2846989cf23SStefano Zampini   Mat_SeqAIJ             *offd = (Mat_SeqAIJ*)(aij->B->data);
2856989cf23SStefano Zampini   Mat                    lA;
2866989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2876989cf23SStefano Zampini   IS                     is;
2886989cf23SStefano Zampini   MPI_Comm               comm;
2896989cf23SStefano Zampini   void                   *ptrs[2];
2906989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
2916989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
2926989cf23SStefano Zampini   PetscInt               *di,*dj,*oi,*oj;
2936989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
294e363d98aSStefano Zampini   PetscInt               lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
2956989cf23SStefano Zampini   PetscErrorCode         ierr;
2966989cf23SStefano Zampini 
297ab4d48faSStefano Zampini   PetscFunctionBegin;
2986989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
2996989cf23SStefano Zampini   if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present");
3006989cf23SStefano Zampini 
3016989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
3026989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
3036989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
3046989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
3056989cf23SStefano Zampini   di   = diag->i;
3066989cf23SStefano Zampini   dj   = diag->j;
3076989cf23SStefano Zampini   dd   = diag->a;
3086989cf23SStefano Zampini   oc   = aij->B->cmap->n;
3096989cf23SStefano Zampini   oi   = offd->i;
3106989cf23SStefano Zampini   oj   = offd->j;
3116989cf23SStefano Zampini   od   = offd->a;
3126989cf23SStefano Zampini   nnz  = diag->i[dr] + offd->i[dr];
3136989cf23SStefano Zampini 
3146989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
3156989cf23SStefano Zampini   ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
3166989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
3176989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
318e363d98aSStefano Zampini   if (dr) {
3196989cf23SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
3206989cf23SStefano Zampini     for (i=0; i<dc; i++) aux[i]    = i+stc;
3216989cf23SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i];
3226989cf23SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
323e363d98aSStefano Zampini     lc   = dc+oc;
324e363d98aSStefano Zampini   } else {
325e363d98aSStefano Zampini     ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
326e363d98aSStefano Zampini     lc   = 0;
327e363d98aSStefano Zampini   }
3286989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
3296989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
3306989cf23SStefano Zampini 
3316989cf23SStefano Zampini   /* create MATIS object */
3326989cf23SStefano Zampini   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
3336989cf23SStefano Zampini   ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
3346989cf23SStefano Zampini   ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
3356989cf23SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
3366989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3376989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3386989cf23SStefano Zampini 
3396989cf23SStefano Zampini   /* merge local matrices */
3406989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
3416989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
3426989cf23SStefano Zampini   ii   = aux;
3436989cf23SStefano Zampini   jj   = aux+dr+1;
3446989cf23SStefano Zampini   aa   = data;
3456989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
3466989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
3476989cf23SStefano Zampini   {
3486989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
3496989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
3506989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
3516989cf23SStefano Zampini   }
3526989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
3536989cf23SStefano Zampini   ii   = aux;
3546989cf23SStefano Zampini   jj   = aux+dr+1;
3556989cf23SStefano Zampini   aa   = data;
356e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
3576989cf23SStefano Zampini 
3586989cf23SStefano Zampini   /* create containers to destroy the data */
3596989cf23SStefano Zampini   ptrs[0] = aux;
3606989cf23SStefano Zampini   ptrs[1] = data;
3616989cf23SStefano Zampini   for (i=0; i<2; i++) {
3626989cf23SStefano Zampini     PetscContainer c;
3636989cf23SStefano Zampini 
3646989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
3656989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
366b81c21eeSStefano Zampini     ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
3676989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
3686989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
3696989cf23SStefano Zampini   }
3706989cf23SStefano Zampini 
3716989cf23SStefano Zampini   /* finalize matrix */
3726989cf23SStefano Zampini   ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
3736989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
3746989cf23SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3756989cf23SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3766989cf23SStefano Zampini   PetscFunctionReturn(0);
3776989cf23SStefano Zampini }
3786989cf23SStefano Zampini 
379cf0a3239SStefano Zampini /*@
3803d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
381cf0a3239SStefano Zampini 
382cf0a3239SStefano Zampini    Collective on MPI_Comm
383cf0a3239SStefano Zampini 
384cf0a3239SStefano Zampini    Input Parameters:
385cf0a3239SStefano Zampini +  A - the matrix
386cf0a3239SStefano Zampini 
387cf0a3239SStefano Zampini    Level: advanced
388cf0a3239SStefano Zampini 
38995452b02SPatrick Sanan    Notes:
39095452b02SPatrick Sanan     This function does not need to be called by the user.
391cf0a3239SStefano Zampini 
392cf0a3239SStefano Zampini .keywords: matrix
393cf0a3239SStefano Zampini 
394cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
395cf0a3239SStefano Zampini @*/
396cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
397cf0a3239SStefano Zampini {
3987fa8f2d3SStefano Zampini   PetscErrorCode ierr;
3997fa8f2d3SStefano Zampini 
4007fa8f2d3SStefano Zampini   PetscFunctionBegin;
401cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
402cf0a3239SStefano Zampini   PetscValidType(A,1);
403cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
4047fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
4057fa8f2d3SStefano Zampini }
4067fa8f2d3SStefano Zampini 
4075e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
4085e3038f0Sstefano_zampini {
4095e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
4105e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
4115e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
4125e3038f0Sstefano_zampini   MPI_Comm               comm;
4135b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
4145b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
4159e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
4165e3038f0Sstefano_zampini   PetscErrorCode         ierr;
4175e3038f0Sstefano_zampini 
418ab4d48faSStefano Zampini   PetscFunctionBegin;
4195e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
4205e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
4215e3038f0Sstefano_zampini   rnest  = NULL;
4225e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
4235e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
4245e3038f0Sstefano_zampini 
4255e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
4265e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
4275e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4285e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
4295e3038f0Sstefano_zampini     if (isnest) {
4305e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
4315e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
4325e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
4335e3038f0Sstefano_zampini     }
4345e3038f0Sstefano_zampini   }
4355e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
4365b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
4379e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
4385e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
4399e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
4405e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
4415e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4425e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
4435e3038f0Sstefano_zampini       PetscBool ismatis;
4449e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
4455e3038f0Sstefano_zampini 
4465e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
4475e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
4485e3038f0Sstefano_zampini 
4495e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
4509e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
4519e7b2b25Sstefano_zampini       if (istrans[ij]) {
4529e7b2b25Sstefano_zampini         Mat T,lT;
4539e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
4549e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
4559e7b2b25Sstefano_zampini         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) (transposed) is not of type MATIS",i,j);
4569e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
4579e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
4589e7b2b25Sstefano_zampini       } else {
4595e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
4605e3038f0Sstefano_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);
4619e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
4629e7b2b25Sstefano_zampini       }
4635e3038f0Sstefano_zampini 
4645e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
4655e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
4669e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
4675e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
4685e3038f0Sstefano_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);
4695e3038f0Sstefano_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);
4705e3038f0Sstefano_zampini       lr[i] = l1;
4715e3038f0Sstefano_zampini       lc[j] = l2;
4725e3038f0Sstefano_zampini 
4735e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
4745e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
4755e3038f0Sstefano_zampini     }
4765e3038f0Sstefano_zampini   }
4775e3038f0Sstefano_zampini 
4785e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
4795e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
4805e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4815e3038f0Sstefano_zampini     rl2g = NULL;
4825e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
4835e3038f0Sstefano_zampini       PetscInt n1,n2;
4845e3038f0Sstefano_zampini 
4855e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
4869e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
4879e7b2b25Sstefano_zampini         Mat T;
4889e7b2b25Sstefano_zampini 
4899e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
4909e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
4919e7b2b25Sstefano_zampini       } else {
4925e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
4939e7b2b25Sstefano_zampini       }
4945e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
4955e3038f0Sstefano_zampini       if (!n1) continue;
4965e3038f0Sstefano_zampini       if (!rl2g) {
4975e3038f0Sstefano_zampini         rl2g = cl2g;
4985e3038f0Sstefano_zampini       } else {
4995e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
5005e3038f0Sstefano_zampini         PetscBool      same;
5015e3038f0Sstefano_zampini 
5025e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
5035e3038f0Sstefano_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);
5045e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
5055e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
5065e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
5075e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
5085e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
5095e3038f0Sstefano_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);
5105e3038f0Sstefano_zampini       }
5115e3038f0Sstefano_zampini     }
5125e3038f0Sstefano_zampini   }
5135e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
5145e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
5155e3038f0Sstefano_zampini     rl2g = NULL;
5165e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
5175e3038f0Sstefano_zampini       PetscInt n1,n2;
5185e3038f0Sstefano_zampini 
5195e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
5209e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
5219e7b2b25Sstefano_zampini         Mat T;
5229e7b2b25Sstefano_zampini 
5239e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
5249e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
5259e7b2b25Sstefano_zampini       } else {
5265e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
5279e7b2b25Sstefano_zampini       }
5285e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
5295e3038f0Sstefano_zampini       if (!n1) continue;
5305e3038f0Sstefano_zampini       if (!rl2g) {
5315e3038f0Sstefano_zampini         rl2g = cl2g;
5325e3038f0Sstefano_zampini       } else {
5335e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
5345e3038f0Sstefano_zampini         PetscBool      same;
5355e3038f0Sstefano_zampini 
5365e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
5375e3038f0Sstefano_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);
5385e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
5395e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
5405e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
5415e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
5425e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
5435e3038f0Sstefano_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);
5445e3038f0Sstefano_zampini       }
5455e3038f0Sstefano_zampini     }
5465e3038f0Sstefano_zampini   }
5475e3038f0Sstefano_zampini #endif
5485e3038f0Sstefano_zampini 
5495e3038f0Sstefano_zampini   B = NULL;
5505e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
5515b003df0Sstefano_zampini     PetscInt stl;
5525b003df0Sstefano_zampini 
5535e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
5545e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
5555e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
5565b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
5575e3038f0Sstefano_zampini       Mat            usedmat;
5585e3038f0Sstefano_zampini       Mat_IS         *matis;
5595e3038f0Sstefano_zampini       const PetscInt *idxs;
5605e3038f0Sstefano_zampini 
5615e3038f0Sstefano_zampini       /* local IS for local NEST */
5625b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
5635e3038f0Sstefano_zampini 
5645e3038f0Sstefano_zampini       /* l2gmap */
5655e3038f0Sstefano_zampini       j = 0;
5665e3038f0Sstefano_zampini       usedmat = nest[i][j];
5679e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
5689e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
5699e7b2b25Sstefano_zampini 
5709e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
5719e7b2b25Sstefano_zampini         Mat T;
5729e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
5739e7b2b25Sstefano_zampini         usedmat = T;
5749e7b2b25Sstefano_zampini       }
57582d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
5765e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
5775e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
5789e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
5799e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
5809e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
5819e7b2b25Sstefano_zampini       } else {
5825e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
5835e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
5849e7b2b25Sstefano_zampini       }
5855e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
5865e3038f0Sstefano_zampini       stl += lr[i];
5875e3038f0Sstefano_zampini     }
5885e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
5895e3038f0Sstefano_zampini 
5905e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
5915e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
5925e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
5935b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
5945e3038f0Sstefano_zampini       Mat            usedmat;
5955e3038f0Sstefano_zampini       Mat_IS         *matis;
5965e3038f0Sstefano_zampini       const PetscInt *idxs;
5975e3038f0Sstefano_zampini 
5985e3038f0Sstefano_zampini       /* local IS for local NEST */
5995b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
6005e3038f0Sstefano_zampini 
6015e3038f0Sstefano_zampini       /* l2gmap */
6025e3038f0Sstefano_zampini       j = 0;
6035e3038f0Sstefano_zampini       usedmat = nest[j][i];
6049e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
6059e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
6069e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
6079e7b2b25Sstefano_zampini         Mat T;
6089e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
6099e7b2b25Sstefano_zampini         usedmat = T;
6109e7b2b25Sstefano_zampini       }
61182d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
6125e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
6135e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
6149e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
6159e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
6169e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
6179e7b2b25Sstefano_zampini       } else {
6185e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
6195e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
6209e7b2b25Sstefano_zampini       }
6215e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
6225e3038f0Sstefano_zampini       stl += lc[i];
6235e3038f0Sstefano_zampini     }
6245e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
6255e3038f0Sstefano_zampini 
6265e3038f0Sstefano_zampini     /* Create MATIS */
6275e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
6285e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
6295e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
6305e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
6315e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
6325e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
6335e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
6345e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
6355e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
6369e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
6379e7b2b25Sstefano_zampini       if (istrans[i]) {
6389e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
6399e7b2b25Sstefano_zampini       }
6409e7b2b25Sstefano_zampini     }
6415e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
6425e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
6435e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6445e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6455e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
6465e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
6475e3038f0Sstefano_zampini     } else {
6485e3038f0Sstefano_zampini       *newmat = B;
6495e3038f0Sstefano_zampini     }
6505e3038f0Sstefano_zampini   } else {
6515e3038f0Sstefano_zampini     if (lreuse) {
6525e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
6535e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
6545e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
6555e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
6565e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
6579e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
6589e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
6599e7b2b25Sstefano_zampini             }
6605e3038f0Sstefano_zampini           }
6615e3038f0Sstefano_zampini         }
6625e3038f0Sstefano_zampini       }
6635e3038f0Sstefano_zampini     } else {
6645b003df0Sstefano_zampini       PetscInt stl;
6655b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
6665b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
6675b003df0Sstefano_zampini         stl  += lr[i];
6685e3038f0Sstefano_zampini       }
6695b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
6705b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
6715b003df0Sstefano_zampini         stl  += lc[i];
6725e3038f0Sstefano_zampini       }
6735e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
674ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
6759e7b2b25Sstefano_zampini         if (istrans[i]) {
6769e7b2b25Sstefano_zampini           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
6779e7b2b25Sstefano_zampini         }
678ab4d48faSStefano Zampini       }
6795e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
6805e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
6815e3038f0Sstefano_zampini     }
6825e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6835e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6845e3038f0Sstefano_zampini   }
6855e3038f0Sstefano_zampini 
6865b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
6875b003df0Sstefano_zampini   convert = PETSC_FALSE;
6885b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
6895b003df0Sstefano_zampini   if (convert) {
6905b003df0Sstefano_zampini     Mat              M;
6915b003df0Sstefano_zampini     MatISLocalFields lf;
6925b003df0Sstefano_zampini     PetscContainer   c;
6935b003df0Sstefano_zampini 
6945b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
6955b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
6965b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
6975b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
6985b003df0Sstefano_zampini 
6995b003df0Sstefano_zampini     /* attach local fields to the matrix */
7005b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
7015b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
7025b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
7035b003df0Sstefano_zampini       PetscInt n,st;
7045b003df0Sstefano_zampini 
7055b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
7065b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
7075b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
7085b003df0Sstefano_zampini     }
7095b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
7105b003df0Sstefano_zampini       PetscInt n,st;
7115b003df0Sstefano_zampini 
7125b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
7135b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
7145b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
7155b003df0Sstefano_zampini     }
7165b003df0Sstefano_zampini     lf->nr = nr;
7175b003df0Sstefano_zampini     lf->nc = nc;
7185b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
7195b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
7205b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
7215b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
7225b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
7235b003df0Sstefano_zampini   }
7245b003df0Sstefano_zampini 
7255e3038f0Sstefano_zampini   /* Free workspace */
7265e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
7275e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
7285e3038f0Sstefano_zampini   }
7295e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
7305e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
7315e3038f0Sstefano_zampini   }
7329e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
7335b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
7345e3038f0Sstefano_zampini   PetscFunctionReturn(0);
7355e3038f0Sstefano_zampini }
7365e3038f0Sstefano_zampini 
737ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
738ad219c80Sstefano_zampini {
739ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
740ad219c80Sstefano_zampini   Vec               ll,rr;
741ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
742ad219c80Sstefano_zampini   PetscScalar       *x,*y;
743ad219c80Sstefano_zampini   PetscErrorCode    ierr;
744ad219c80Sstefano_zampini 
745ad219c80Sstefano_zampini   PetscFunctionBegin;
746ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
747ad219c80Sstefano_zampini   if (l) {
748ad219c80Sstefano_zampini     ll   = matis->y;
749ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
750ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
751ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
752ad219c80Sstefano_zampini   } else {
753ad219c80Sstefano_zampini     ll = NULL;
754ad219c80Sstefano_zampini   }
755ad219c80Sstefano_zampini   if (r) {
756ad219c80Sstefano_zampini     rr   = matis->x;
757ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
758ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
759ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
760ad219c80Sstefano_zampini   } else {
761ad219c80Sstefano_zampini     rr = NULL;
762ad219c80Sstefano_zampini   }
763ad219c80Sstefano_zampini   if (ll) {
764ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
765ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
766ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
767ad219c80Sstefano_zampini   }
768ad219c80Sstefano_zampini   if (rr) {
769ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
770ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
771ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
772ad219c80Sstefano_zampini   }
773ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
774ad219c80Sstefano_zampini   PetscFunctionReturn(0);
775ad219c80Sstefano_zampini }
776ad219c80Sstefano_zampini 
7777fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
7787fa8f2d3SStefano Zampini {
7797fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
7807fa8f2d3SStefano Zampini   MatInfo        info;
7817fa8f2d3SStefano Zampini   PetscReal      isend[6],irecv[6];
7827fa8f2d3SStefano Zampini   PetscInt       bs;
7837fa8f2d3SStefano Zampini   PetscErrorCode ierr;
7847fa8f2d3SStefano Zampini 
7857fa8f2d3SStefano Zampini   PetscFunctionBegin;
7867fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
7877fa8f2d3SStefano Zampini   if (matis->A->ops->getinfo) {
7887fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
7897fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
7907fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
7917fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
7927fa8f2d3SStefano Zampini     isend[3] = info.memory;
7937fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
7947fa8f2d3SStefano Zampini   } else {
7957fa8f2d3SStefano Zampini     isend[0] = 0.;
7967fa8f2d3SStefano Zampini     isend[1] = 0.;
7977fa8f2d3SStefano Zampini     isend[2] = 0.;
7987fa8f2d3SStefano Zampini     isend[3] = 0.;
7997fa8f2d3SStefano Zampini     isend[4] = 0.;
8007fa8f2d3SStefano Zampini   }
8017fa8f2d3SStefano Zampini   isend[5] = matis->A->num_ass;
8027fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
8037fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
8047fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
8057fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
8067fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
8077fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
8087fa8f2d3SStefano Zampini     ginfo->assemblies   = isend[5];
8097fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
8107fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
8117fa8f2d3SStefano Zampini 
8127fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
8137fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
8147fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
8157fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
8167fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
8177fa8f2d3SStefano Zampini     ginfo->assemblies   = irecv[5];
8187fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
8197fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
8207fa8f2d3SStefano Zampini 
8217fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
8227fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
8237fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
8247fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
8257fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
8267fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
827d7f69cd0SStefano Zampini   }
828d7f69cd0SStefano Zampini   ginfo->block_size        = bs;
829d7f69cd0SStefano Zampini   ginfo->fill_ratio_given  = 0;
830d7f69cd0SStefano Zampini   ginfo->fill_ratio_needed = 0;
831d7f69cd0SStefano Zampini   ginfo->factor_mallocs    = 0;
8325e3038f0Sstefano_zampini   PetscFunctionReturn(0);
8335e3038f0Sstefano_zampini }
8345e3038f0Sstefano_zampini 
835d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
836d7f69cd0SStefano Zampini {
837d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
838d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
839d7f69cd0SStefano Zampini 
840d7f69cd0SStefano Zampini   PetscFunctionBegin;
841cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
842cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
843d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
844d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
845d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
846d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
847d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
848d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
849cf37664fSBarry Smith   } else {
850cf37664fSBarry Smith     C = *B;
851d7f69cd0SStefano Zampini   }
852d7f69cd0SStefano Zampini 
853d7f69cd0SStefano Zampini   /* perform local transposition */
854d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
855d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
856d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
857d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
858d7f69cd0SStefano Zampini 
859cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
860d7f69cd0SStefano Zampini     *B = C;
861d7f69cd0SStefano Zampini   } else {
862d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
863d7f69cd0SStefano Zampini   }
8647aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8657aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
866d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
867d7f69cd0SStefano Zampini }
868d7f69cd0SStefano Zampini 
8693fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
8703fd1c9e7SStefano Zampini {
8713fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
8723fd1c9e7SStefano Zampini   PetscErrorCode ierr;
8733fd1c9e7SStefano Zampini 
8743fd1c9e7SStefano Zampini   PetscFunctionBegin;
8754b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
8763fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8773fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8783fd1c9e7SStefano Zampini   }
8793fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
8803fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
8813fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
8823fd1c9e7SStefano Zampini }
8833fd1c9e7SStefano Zampini 
8843fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
8853fd1c9e7SStefano Zampini {
8864b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
8873fd1c9e7SStefano Zampini   PetscErrorCode ierr;
8883fd1c9e7SStefano Zampini 
8893fd1c9e7SStefano Zampini   PetscFunctionBegin;
8904b89b9cdSStefano Zampini   ierr = VecSet(is->y,a);CHKERRQ(ierr);
8913fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
8923fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
8933fd1c9e7SStefano Zampini }
8943fd1c9e7SStefano Zampini 
895f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
896f26d0771SStefano Zampini {
897f26d0771SStefano Zampini   PetscErrorCode ierr;
898f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
899f26d0771SStefano Zampini 
900f26d0771SStefano Zampini   PetscFunctionBegin;
901f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
902f26d0771SStefano 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);
903f26d0771SStefano Zampini #endif
904f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
905f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
906b4f971dfSStefano Zampini   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
907f26d0771SStefano Zampini   PetscFunctionReturn(0);
908f26d0771SStefano Zampini }
909f26d0771SStefano Zampini 
910f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
911f26d0771SStefano Zampini {
912f26d0771SStefano Zampini   PetscErrorCode ierr;
913f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
914f26d0771SStefano Zampini 
915f26d0771SStefano Zampini   PetscFunctionBegin;
916f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
917f26d0771SStefano 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);
918f26d0771SStefano Zampini #endif
919f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
920f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
921b4f971dfSStefano Zampini   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
922f26d0771SStefano Zampini   PetscFunctionReturn(0);
923f26d0771SStefano Zampini }
924f26d0771SStefano Zampini 
925f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
926a8116848SStefano Zampini {
927a8116848SStefano Zampini   PetscInt      *owners = map->range;
928a8116848SStefano Zampini   PetscInt       n      = map->n;
929a8116848SStefano Zampini   PetscSF        sf;
930a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
931a8116848SStefano Zampini   PetscSFNode   *ridxs;
932a8116848SStefano Zampini   PetscMPIInt    rank;
933a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
934a8116848SStefano Zampini   PetscErrorCode ierr;
935a8116848SStefano Zampini 
936a8116848SStefano Zampini   PetscFunctionBegin;
937fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
938a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
939a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
940a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
941a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
942a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
943a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
944a8116848SStefano Zampini     const PetscInt idx = idxs[r];
945a8116848SStefano 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);
946a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
947a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
948a8116848SStefano Zampini     }
949a8116848SStefano Zampini     ridxs[r].rank = p;
950a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
951a8116848SStefano Zampini   }
952a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
953a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
954a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
955a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
956f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
957a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
958f0ae7da4SStefano Zampini 
959f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
960a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
961a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
962a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
963a8116848SStefano Zampini     start -= cum;
964a8116848SStefano Zampini     cum = 0;
965a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
966a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
967a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
968a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
969a8116848SStefano Zampini   }
970a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
971a8116848SStefano Zampini   /* Compress and put in indices */
972a8116848SStefano Zampini   for (r = 0; r < n; ++r)
973a8116848SStefano Zampini     if (lidxs[r] >= 0) {
974a8116848SStefano Zampini       if (work) work[len] = work[r];
975a8116848SStefano Zampini       lidxs[len++] = r;
976a8116848SStefano Zampini     }
977a8116848SStefano Zampini   if (on) *on = len;
978a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
979a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
980a8116848SStefano Zampini   PetscFunctionReturn(0);
981a8116848SStefano Zampini }
982a8116848SStefano Zampini 
9837dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
984a8116848SStefano Zampini {
985a8116848SStefano Zampini   Mat               locmat,newlocmat;
986a8116848SStefano Zampini   Mat_IS            *newmatis;
987a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
988a8116848SStefano Zampini   Vec               rtest,ltest;
989a8116848SStefano Zampini   const PetscScalar *array;
990a8116848SStefano Zampini #endif
991a8116848SStefano Zampini   const PetscInt    *idxs;
992a8116848SStefano Zampini   PetscInt          i,m,n;
993a8116848SStefano Zampini   PetscErrorCode    ierr;
994a8116848SStefano Zampini 
995a8116848SStefano Zampini   PetscFunctionBegin;
996a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
997a8116848SStefano Zampini     PetscBool ismatis;
998a8116848SStefano Zampini 
999a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1000a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1001a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1002a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
1003a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1004a8116848SStefano Zampini   }
1005a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
1006a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1007a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
1008a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
1009a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1010a8116848SStefano Zampini   for (i=0;i<n;i++) {
1011a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1012a8116848SStefano Zampini   }
1013a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
1014a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
1015a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
1016a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
1017a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
1018fd479f66SMatthew 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]));
1019a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
1020a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
1021a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1022a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1023a8116848SStefano Zampini   for (i=0;i<n;i++) {
1024a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1025a8116848SStefano Zampini   }
1026a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
1027a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
1028a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
1029a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
1030a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
1031fd479f66SMatthew 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]));
1032a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
1033a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
1034a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
1035a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
1036a8116848SStefano Zampini #endif
1037a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1038a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
1039a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1040a8116848SStefano Zampini     IS                     is;
1041a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1042306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
1043a8116848SStefano Zampini     MPI_Comm               comm;
1044a8116848SStefano Zampini 
1045a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
1046306cf5c7SStefano Zampini     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
1047306cf5c7SStefano Zampini     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
1048306cf5c7SStefano Zampini     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
1049306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
1050306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
1051a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
1052a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1053a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1054a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1055a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1056306cf5c7SStefano Zampini     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
1057a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
1058a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1059f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1060a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
10613d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
10623d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1063a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
1064a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
1065a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1066a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1067a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
10683d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
1069a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1070a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
10713d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1072a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1073a8116848SStefano Zampini         lidxs[newloc] = i;
1074a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1075a8116848SStefano Zampini       }
1076a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1077a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1078306cf5c7SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
1079a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1080a8116848SStefano Zampini     /* local is to extract local submatrix */
1081a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1082a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
1083a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
1084a8116848SStefano Zampini       PetscBool cong;
108526b0207aSStefano Zampini 
1086a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
1087a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
1088a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
1089a8116848SStefano Zampini     }
1090268753edSStefano Zampini     if (mat->congruentlayouts && irow == icol && matis->csf == matis->sf) {
1091a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
1092a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
1093a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1094a8116848SStefano Zampini     } else {
1095a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1096a8116848SStefano Zampini 
1097a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
1098a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1099f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1100a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
11013d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1102a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
1103a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
1104a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1105a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
1106a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
11073d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
1108a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1109a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
11103d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1111a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1112a8116848SStefano Zampini           lidxs[newloc] = i;
1113a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1114a8116848SStefano Zampini         }
1115a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1116a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1117306cf5c7SStefano Zampini       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
1118a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
1119a8116848SStefano Zampini       /* local is to extract local submatrix */
1120a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
1121a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1122a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1123a8116848SStefano Zampini     }
1124a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1125a8116848SStefano Zampini   } else {
1126a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
1127a8116848SStefano Zampini   }
1128a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
1129a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
11307dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
1131a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1132a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
1133a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
1134a8116848SStefano Zampini   }
1135a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1136a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1137a8116848SStefano Zampini   PetscFunctionReturn(0);
1138a8116848SStefano Zampini }
1139a8116848SStefano Zampini 
1140a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
11412b404112SStefano Zampini {
11422b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
11432b404112SStefano Zampini   PetscBool      ismatis;
11442b404112SStefano Zampini   PetscErrorCode ierr;
11452b404112SStefano Zampini 
11462b404112SStefano Zampini   PetscFunctionBegin;
11472b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
11482b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
11492b404112SStefano Zampini   b = (Mat_IS*)B->data;
11502b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
1151cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
11522b404112SStefano Zampini   PetscFunctionReturn(0);
11532b404112SStefano Zampini }
11542b404112SStefano Zampini 
1155a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
11566bd84002SStefano Zampini {
1157527b2640SStefano Zampini   Vec               v;
1158527b2640SStefano Zampini   const PetscScalar *array;
1159527b2640SStefano Zampini   PetscInt          i,n;
11606bd84002SStefano Zampini   PetscErrorCode    ierr;
11616bd84002SStefano Zampini 
11626bd84002SStefano Zampini   PetscFunctionBegin;
1163527b2640SStefano Zampini   *missing = PETSC_FALSE;
1164527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
1165527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
1166527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1167527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
1168527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
1169527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
1170527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1171527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
1172527b2640SStefano Zampini   if (d) {
1173527b2640SStefano Zampini     *d = -1;
1174527b2640SStefano Zampini     if (*missing) {
1175527b2640SStefano Zampini       PetscInt rstart;
1176527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
1177527b2640SStefano Zampini       *d = i+rstart;
1178527b2640SStefano Zampini     }
1179527b2640SStefano Zampini   }
11806bd84002SStefano Zampini   PetscFunctionReturn(0);
11816bd84002SStefano Zampini }
11826bd84002SStefano Zampini 
1183cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
118428f4e0baSStefano Zampini {
118528f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
118628f4e0baSStefano Zampini   const PetscInt *gidxs;
11874f2d7cafSStefano Zampini   PetscInt       nleaves;
118828f4e0baSStefano Zampini   PetscErrorCode ierr;
118928f4e0baSStefano Zampini 
119028f4e0baSStefano Zampini   PetscFunctionBegin;
11914f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
1192*75d48cdbSStefano Zampini   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
1193*75d48cdbSStefano Zampini   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
119428f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
11953bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
11964f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
11974f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
11983bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
11994f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
1200a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
12013d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
1202a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
1203a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
12043d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
1205a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
12063d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
1207a8116848SStefano Zampini   } else {
1208a8116848SStefano Zampini     matis->csf = matis->sf;
1209a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1210a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1211a8116848SStefano Zampini   }
121228f4e0baSStefano Zampini   PetscFunctionReturn(0);
121328f4e0baSStefano Zampini }
12142e1947a5SStefano Zampini 
1215eb82efa4SStefano Zampini /*@
1216*75d48cdbSStefano Zampini    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
1217*75d48cdbSStefano Zampini 
1218*75d48cdbSStefano Zampini    Collective on MPI_Comm
1219*75d48cdbSStefano Zampini 
1220*75d48cdbSStefano Zampini    Input Parameters:
1221*75d48cdbSStefano Zampini +  A - the matrix
1222*75d48cdbSStefano Zampini -  store - the boolean flag
1223*75d48cdbSStefano Zampini 
1224*75d48cdbSStefano Zampini    Level: advanced
1225*75d48cdbSStefano Zampini 
1226*75d48cdbSStefano Zampini    Notes:
1227*75d48cdbSStefano Zampini 
1228*75d48cdbSStefano Zampini .keywords: matrix
1229*75d48cdbSStefano Zampini 
1230*75d48cdbSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP()
1231*75d48cdbSStefano Zampini @*/
1232*75d48cdbSStefano Zampini PetscErrorCode  MatISStoreL2L(Mat A, PetscBool store)
1233*75d48cdbSStefano Zampini {
1234*75d48cdbSStefano Zampini   PetscErrorCode ierr;
1235*75d48cdbSStefano Zampini 
1236*75d48cdbSStefano Zampini   PetscFunctionBegin;
1237*75d48cdbSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1238*75d48cdbSStefano Zampini   PetscValidType(A,1);
1239*75d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A,store,2);
1240*75d48cdbSStefano Zampini   ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr);
1241*75d48cdbSStefano Zampini   PetscFunctionReturn(0);
1242*75d48cdbSStefano Zampini }
1243*75d48cdbSStefano Zampini 
1244*75d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
1245*75d48cdbSStefano Zampini {
1246*75d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
1247*75d48cdbSStefano Zampini   PetscErrorCode ierr;
1248*75d48cdbSStefano Zampini 
1249*75d48cdbSStefano Zampini   PetscFunctionBegin;
1250*75d48cdbSStefano Zampini   matis->storel2l = store;
1251*75d48cdbSStefano Zampini   if (!store) {
1252*75d48cdbSStefano Zampini     ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr);
1253*75d48cdbSStefano Zampini   }
1254*75d48cdbSStefano Zampini   PetscFunctionReturn(0);
1255*75d48cdbSStefano Zampini }
1256*75d48cdbSStefano Zampini 
1257*75d48cdbSStefano Zampini /*@
1258a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1259a88811baSStefano Zampini 
1260a88811baSStefano Zampini    Collective on MPI_Comm
1261a88811baSStefano Zampini 
1262a88811baSStefano Zampini    Input Parameters:
1263a88811baSStefano Zampini +  B - the matrix
1264a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1265a88811baSStefano Zampini            (same value is used for all local rows)
1266a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1267a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1268a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1269a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1270a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1271a88811baSStefano Zampini            the diagonal entry even if it is zero.
1272a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1273a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1274a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1275a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1276a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1277a88811baSStefano Zampini            structure. The size of this array is equal to the number
1278a88811baSStefano Zampini            of local rows, i.e 'm'.
1279a88811baSStefano Zampini 
1280a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1281a88811baSStefano Zampini 
1282a88811baSStefano Zampini    Level: intermediate
1283a88811baSStefano Zampini 
128495452b02SPatrick Sanan    Notes:
128595452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1286a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1287a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1288a88811baSStefano Zampini 
1289a88811baSStefano Zampini .keywords: matrix
1290a88811baSStefano Zampini 
12913c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1292a88811baSStefano Zampini @*/
12932e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
12942e1947a5SStefano Zampini {
12952e1947a5SStefano Zampini   PetscErrorCode ierr;
12962e1947a5SStefano Zampini 
12972e1947a5SStefano Zampini   PetscFunctionBegin;
12982e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
12992e1947a5SStefano Zampini   PetscValidType(B,1);
13002e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
13012e1947a5SStefano Zampini   PetscFunctionReturn(0);
13022e1947a5SStefano Zampini }
13032e1947a5SStefano Zampini 
13047230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
13052e1947a5SStefano Zampini {
13062e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
130728f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
13082e1947a5SStefano Zampini   PetscErrorCode ierr;
13092e1947a5SStefano Zampini 
13102e1947a5SStefano Zampini   PetscFunctionBegin;
13116c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1312cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
13134f2d7cafSStefano Zampini 
13144f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
13154f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
13164f2d7cafSStefano Zampini 
13174f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
13184f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
13194f2d7cafSStefano Zampini 
132028f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
132128f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
132228f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
132328f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
13244f2d7cafSStefano Zampini 
13254f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
132628f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
13270f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
13280f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
13290f2f62c7SStefano Zampini #endif
13304f2d7cafSStefano Zampini 
13314f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
133228f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
13334f2d7cafSStefano Zampini 
13344f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
133528f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
13360f2f62c7SStefano Zampini 
13370f2f62c7SStefano Zampini   /* for other matrix types */
13380f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
13392e1947a5SStefano Zampini   PetscFunctionReturn(0);
13402e1947a5SStefano Zampini }
1341b4319ba4SBarry Smith 
13423927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
13433927de2eSStefano Zampini {
13443927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
13453927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1346ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
13473927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
13483927de2eSStefano Zampini   PetscInt        lrows,lcols;
13493927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
13503927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
13513927de2eSStefano Zampini   PetscBool       isdense,issbaij;
13523927de2eSStefano Zampini   PetscErrorCode  ierr;
13533927de2eSStefano Zampini 
13543927de2eSStefano Zampini   PetscFunctionBegin;
13553927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
13563927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
13573927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
13583927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
13593927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
13603927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1361ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1362ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
13637230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1364ecf5a873SStefano Zampini   } else {
1365ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1366ecf5a873SStefano Zampini   }
1367ecf5a873SStefano Zampini 
13683927de2eSStefano Zampini   if (issbaij) {
13693927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
13703927de2eSStefano Zampini   }
13713927de2eSStefano Zampini   /*
1372ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
13733927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
13743927de2eSStefano Zampini   */
1375cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
13763927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
13773927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
13783927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
13793927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
13803927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
13813927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
13823927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
13833927de2eSStefano Zampini       row_ownership[j] = i;
13843927de2eSStefano Zampini     }
13853927de2eSStefano Zampini   }
13867230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
13873927de2eSStefano Zampini 
13883927de2eSStefano Zampini   /*
13893927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
13903927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
13913927de2eSStefano Zampini   */
13923927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
13933927de2eSStefano Zampini   /* preallocation as a MATAIJ */
13943927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
13953927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
139612dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
139712dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1398ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
13993927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
14003927de2eSStefano Zampini           my_dnz[i] += 1;
14013927de2eSStefano Zampini         } else { /* offdiag block */
14023927de2eSStefano Zampini           my_onz[i] += 1;
14033927de2eSStefano Zampini         }
14043927de2eSStefano Zampini       }
14053927de2eSStefano Zampini     }
1406bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1407bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1408bb1015c3SStefano Zampini     PetscBool      done;
1409bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1410938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1411bb1015c3SStefano Zampini     jptr = jj;
1412bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1413bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1414bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1415bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1416bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1417bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1418bb1015c3SStefano Zampini           my_dnz[i] += 1;
1419bb1015c3SStefano Zampini         } else { /* offdiag block */
1420bb1015c3SStefano Zampini           my_onz[i] += 1;
1421bb1015c3SStefano Zampini         }
1422bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1423bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1424bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1425bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1426bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1427bb1015c3SStefano Zampini           } else {
1428bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1429bb1015c3SStefano Zampini           }
1430bb1015c3SStefano Zampini         }
1431bb1015c3SStefano Zampini       }
1432bb1015c3SStefano Zampini     }
1433bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1434938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1435bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
14363927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
14373927de2eSStefano Zampini       const PetscInt *cols;
1438ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
14393927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
14403927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
14413927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1442ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
14433927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
14443927de2eSStefano Zampini           my_dnz[i] += 1;
14453927de2eSStefano Zampini         } else { /* offdiag block */
14463927de2eSStefano Zampini           my_onz[i] += 1;
14473927de2eSStefano Zampini         }
14483927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1449d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
14503927de2eSStefano Zampini           owner = row_ownership[index_col];
14513927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1452d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
14533927de2eSStefano Zampini           } else {
1454d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
14553927de2eSStefano Zampini           }
14563927de2eSStefano Zampini         }
14573927de2eSStefano Zampini       }
14583927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
14593927de2eSStefano Zampini     }
14603927de2eSStefano Zampini   }
1461ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
14627230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1463ecf5a873SStefano Zampini   }
14644f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
14653927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1466ecf5a873SStefano Zampini 
1467ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
14683927de2eSStefano Zampini   if (maxreduce) {
14693927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
14703927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1471bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
14723927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
14733927de2eSStefano Zampini   } else {
14743927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
14753927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1476bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
14773927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
14783927de2eSStefano Zampini   }
14793927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
14803927de2eSStefano Zampini 
14813927de2eSStefano Zampini   /* Resize preallocation if overestimated */
14823927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
14833927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
14843927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
14853927de2eSStefano Zampini   }
14861670daf9Sstefano_zampini 
14871670daf9Sstefano_zampini   /* Set preallocation */
1488268753edSStefano Zampini   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
14893927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
14903927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
14913927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
14923927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
14933927de2eSStefano Zampini   }
1494268753edSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
14953927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
14963927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
14973927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
14983927de2eSStefano Zampini   if (issbaij) {
14993927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
15003927de2eSStefano Zampini   }
15013927de2eSStefano Zampini   PetscFunctionReturn(0);
15023927de2eSStefano Zampini }
15033927de2eSStefano Zampini 
15047230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1505b7ce53b6SStefano Zampini {
1506b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1507d9a9e74cSStefano Zampini   Mat            local_mat;
1508b7ce53b6SStefano Zampini   /* info on mat */
15093cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1510b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1511b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1512b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1513b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1514b9ed4604SStefano Zampini #endif
15157c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1516b7ce53b6SStefano Zampini   /* values insertion */
1517b7ce53b6SStefano Zampini   PetscScalar    *array;
1518b7ce53b6SStefano Zampini   /* work */
1519b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1520b7ce53b6SStefano Zampini 
1521b7ce53b6SStefano Zampini   PetscFunctionBegin;
1522b7ce53b6SStefano Zampini   /* get info from mat */
15237c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
15247c03b4e8SStefano Zampini   if (nsubdomains == 1) {
15251670daf9Sstefano_zampini     Mat            B;
15261670daf9Sstefano_zampini     IS             rows,cols;
1527acdf38a7Sstefano_zampini     IS             irows,icols;
15281670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
15291670daf9Sstefano_zampini 
15301670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
15311670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
15321670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
15331670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
1534acdf38a7Sstefano_zampini     ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1535acdf38a7Sstefano_zampini     ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1536acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr);
1537acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr);
1538268753edSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
1539268753edSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1540acdf38a7Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
1541acdf38a7Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
15426104e0f1Sstefano_zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
15437dae84e0SHong Zhang     ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1544acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1545acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1546acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
15477c03b4e8SStefano Zampini     PetscFunctionReturn(0);
15487c03b4e8SStefano Zampini   }
1549b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1550b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
15513cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1552b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1553b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
15544099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1555b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1556b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1557b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1558b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1559b9ed4604SStefano Zampini   lb[0] = isseqdense;
1560b9ed4604SStefano Zampini   lb[1] = isseqaij;
1561b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1562b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1563b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1564b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1565b9ed4604SStefano Zampini #endif
1566b7ce53b6SStefano Zampini 
1567b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
15683927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
15693cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
1570b9ed4604SStefano Zampini     if (!isseqsbaij) {
1571b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1572b9ed4604SStefano Zampini     } else {
1573b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1574b9ed4604SStefano Zampini     }
1575d59cf9ebSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
15763927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1577b7ce53b6SStefano Zampini   } else {
15783cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1579b7ce53b6SStefano Zampini     /* some checks */
1580b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1581b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
15823cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
15836c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
15846c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
15856c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
15866c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
15876c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1588b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1589b7ce53b6SStefano Zampini   }
1590d9a9e74cSStefano Zampini 
1591b9ed4604SStefano Zampini   if (isseqsbaij) {
1592d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1593d9a9e74cSStefano Zampini   } else {
1594d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1595d9a9e74cSStefano Zampini     local_mat = matis->A;
1596d9a9e74cSStefano Zampini   }
1597686e3a49SStefano Zampini 
1598b7ce53b6SStefano Zampini   /* Set values */
1599ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1600b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
160165066ba5SStefano Zampini     PetscInt i,*dummy;
1602ecf5a873SStefano Zampini 
160365066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
160465066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
1605b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1606d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
160765066ba5SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
1608d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
160965066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
1610686e3a49SStefano Zampini   } else if (isseqaij) {
1611ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1612686e3a49SStefano Zampini     PetscBool done;
1613686e3a49SStefano Zampini 
1614d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1615938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1616d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1617686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1618ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1619686e3a49SStefano Zampini     }
1620d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1621938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1622d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1623686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1624ecf5a873SStefano Zampini     PetscInt i;
1625c0962df8SStefano Zampini 
1626686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1627686e3a49SStefano Zampini       PetscInt       j;
1628ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1629686e3a49SStefano Zampini 
1630ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1631ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1632ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1633686e3a49SStefano Zampini     }
1634b7ce53b6SStefano Zampini   }
1635b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1636d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1637b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1638b9ed4604SStefano Zampini   if (isseqdense) {
1639b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1640b7ce53b6SStefano Zampini   }
1641b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1642b7ce53b6SStefano Zampini }
1643b7ce53b6SStefano Zampini 
1644b7ce53b6SStefano Zampini /*@
1645b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1646b7ce53b6SStefano Zampini 
1647b7ce53b6SStefano Zampini   Input Parameter:
1648b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1649b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1650b7ce53b6SStefano Zampini 
1651b7ce53b6SStefano Zampini   Output Parameter:
1652b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1653b7ce53b6SStefano Zampini 
1654b7ce53b6SStefano Zampini   Level: developer
1655b7ce53b6SStefano Zampini 
165695452b02SPatrick Sanan   Notes:
165795452b02SPatrick Sanan     mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1658b7ce53b6SStefano Zampini 
1659b7ce53b6SStefano Zampini .seealso: MATIS
1660b7ce53b6SStefano Zampini @*/
1661b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1662b7ce53b6SStefano Zampini {
1663b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1664b7ce53b6SStefano Zampini 
1665b7ce53b6SStefano Zampini   PetscFunctionBegin;
1666b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1667b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1668b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1669b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1670b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1671b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
16726c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1673b7ce53b6SStefano Zampini   }
1674b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1675b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1676b7ce53b6SStefano Zampini }
1677b7ce53b6SStefano Zampini 
1678ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1679ad6194a2SStefano Zampini {
1680ad6194a2SStefano Zampini   PetscErrorCode ierr;
1681ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1682ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1683ad6194a2SStefano Zampini   Mat            B,localmat;
1684ad6194a2SStefano Zampini 
1685ad6194a2SStefano Zampini   PetscFunctionBegin;
1686ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1687ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1688ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1689e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1690ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1691ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1692b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1693ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1694ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1695ad6194a2SStefano Zampini   *newmat = B;
1696ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1697ad6194a2SStefano Zampini }
1698ad6194a2SStefano Zampini 
1699a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
170069796d55SStefano Zampini {
170169796d55SStefano Zampini   PetscErrorCode ierr;
170269796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
170369796d55SStefano Zampini   PetscBool      local_sym;
170469796d55SStefano Zampini 
170569796d55SStefano Zampini   PetscFunctionBegin;
170669796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1707b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
170869796d55SStefano Zampini   PetscFunctionReturn(0);
170969796d55SStefano Zampini }
171069796d55SStefano Zampini 
1711a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
171269796d55SStefano Zampini {
171369796d55SStefano Zampini   PetscErrorCode ierr;
171469796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
171569796d55SStefano Zampini   PetscBool      local_sym;
171669796d55SStefano Zampini 
171769796d55SStefano Zampini   PetscFunctionBegin;
171869796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1719b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
172069796d55SStefano Zampini   PetscFunctionReturn(0);
172169796d55SStefano Zampini }
172269796d55SStefano Zampini 
172345471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
172445471136SStefano Zampini {
172545471136SStefano Zampini   PetscErrorCode ierr;
172645471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
172745471136SStefano Zampini   PetscBool      local_sym;
172845471136SStefano Zampini 
172945471136SStefano Zampini   PetscFunctionBegin;
173045471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
173145471136SStefano Zampini     *flg = PETSC_FALSE;
173245471136SStefano Zampini     PetscFunctionReturn(0);
173345471136SStefano Zampini   }
173445471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
173545471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
173645471136SStefano Zampini   PetscFunctionReturn(0);
173745471136SStefano Zampini }
173845471136SStefano Zampini 
1739a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1740b4319ba4SBarry Smith {
1741dfbe8321SBarry Smith   PetscErrorCode ierr;
1742b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1743b4319ba4SBarry Smith 
1744b4319ba4SBarry Smith   PetscFunctionBegin;
17456bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1746e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1747e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
17486bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
17496bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
17503fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1751a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1752a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1753a8116848SStefano Zampini   if (b->sf != b->csf) {
1754a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1755a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1756a8116848SStefano Zampini   }
175728f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
175828f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1759bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1760dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1761bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1762b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1763b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
17642e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1765cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1766*75d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr);
1767b4319ba4SBarry Smith   PetscFunctionReturn(0);
1768b4319ba4SBarry Smith }
1769b4319ba4SBarry Smith 
1770a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1771b4319ba4SBarry Smith {
1772dfbe8321SBarry Smith   PetscErrorCode ierr;
1773b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1774b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1775b4319ba4SBarry Smith 
1776b4319ba4SBarry Smith   PetscFunctionBegin;
1777b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1778e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1779e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1780b4319ba4SBarry Smith 
1781b4319ba4SBarry Smith   /* multiply the local matrix */
1782b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1783b4319ba4SBarry Smith 
1784b4319ba4SBarry Smith   /* scatter product back into global memory */
17852dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1786e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1787e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1788b4319ba4SBarry Smith   PetscFunctionReturn(0);
1789b4319ba4SBarry Smith }
1790b4319ba4SBarry Smith 
1791a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
17922e74eeadSLisandro Dalcin {
1793650997f4SStefano Zampini   Vec            temp_vec;
17942e74eeadSLisandro Dalcin   PetscErrorCode ierr;
17952e74eeadSLisandro Dalcin 
17962e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1797650997f4SStefano Zampini   if (v3 != v2) {
1798650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1799650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1800650997f4SStefano Zampini   } else {
1801650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1802650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1803650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1804650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1805650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1806650997f4SStefano Zampini   }
18072e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18082e74eeadSLisandro Dalcin }
18092e74eeadSLisandro Dalcin 
1810a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
18112e74eeadSLisandro Dalcin {
18122e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
18132e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18142e74eeadSLisandro Dalcin 
1815e176bc59SStefano Zampini   PetscFunctionBegin;
18162e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1817e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1818e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18192e74eeadSLisandro Dalcin 
18202e74eeadSLisandro Dalcin   /* multiply the local matrix */
1821e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
18222e74eeadSLisandro Dalcin 
18232e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1824e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1825e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1826e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18272e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18282e74eeadSLisandro Dalcin }
18292e74eeadSLisandro Dalcin 
1830a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
18312e74eeadSLisandro Dalcin {
1832650997f4SStefano Zampini   Vec            temp_vec;
18332e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18342e74eeadSLisandro Dalcin 
18352e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1836650997f4SStefano Zampini   if (v3 != v2) {
1837650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1838650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1839650997f4SStefano Zampini   } else {
1840650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1841650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1842650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1843650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1844650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1845650997f4SStefano Zampini   }
18462e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18472e74eeadSLisandro Dalcin }
18482e74eeadSLisandro Dalcin 
1849a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1850b4319ba4SBarry Smith {
1851b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1852dfbe8321SBarry Smith   PetscErrorCode ierr;
1853b4319ba4SBarry Smith   PetscViewer    sviewer;
1854ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1855b4319ba4SBarry Smith 
1856b4319ba4SBarry Smith   PetscFunctionBegin;
1857ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1858ee2491ecSStefano Zampini   if (isascii)  {
1859ee2491ecSStefano Zampini     PetscViewerFormat format;
1860ee2491ecSStefano Zampini 
1861ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1862ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1863ee2491ecSStefano Zampini   }
1864ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
18653f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1866b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
18673f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
18686e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1869b4319ba4SBarry Smith   PetscFunctionReturn(0);
1870b4319ba4SBarry Smith }
1871b4319ba4SBarry Smith 
1872a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1873b4319ba4SBarry Smith {
1874dfbe8321SBarry Smith   PetscErrorCode ierr;
1875e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1876b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1877b4319ba4SBarry Smith   IS             from,to;
1878e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1879b4319ba4SBarry Smith 
1880b4319ba4SBarry Smith   PetscFunctionBegin;
1881784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1882e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
18833bbff08aSStefano Zampini   /* Destroy any previous data */
188470cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
188570cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
18863fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1887e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1888e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
18891c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
1890872cf891SStefano Zampini   if (is->csf != is->sf) {
1891872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
1892872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
1893872cf891SStefano Zampini   }
189428f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
189528f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
18963bbff08aSStefano Zampini 
18973bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1898fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1899fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1900e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1901e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1902e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1903e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
19046625354bSStefano Zampini   /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */
19056625354bSStefano Zampini   if (rmapping != cmapping && A->rmap->N == A->cmap->N) {
19066625354bSStefano Zampini     PetscBool same,gsame;
19076625354bSStefano Zampini 
19086625354bSStefano Zampini     same = PETSC_FALSE;
19096625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
19106625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
19116625354bSStefano Zampini 
19126625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
19136625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
19146625354bSStefano Zampini       ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr);
19156625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
19166625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
19176625354bSStefano Zampini     }
19186625354bSStefano Zampini     ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
19196625354bSStefano Zampini     if (gsame) cmapping = rmapping;
19206625354bSStefano Zampini   }
19216625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
19226625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
19236625354bSStefano Zampini 
19246625354bSStefano Zampini   /* Create the local matrix A */
1925f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1926e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1927e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1928e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1929ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1930ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1931b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1932c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
1933c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
1934b4319ba4SBarry Smith 
1935f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1936b4319ba4SBarry Smith     /* Create the local work vectors */
19373bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1938b4319ba4SBarry Smith 
1939e176bc59SStefano Zampini     /* setup the global to local scatters */
1940e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1941e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1942784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1943e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1944e176bc59SStefano Zampini     if (rmapping != cmapping) {
1945e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1946e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1947e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1948e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1949e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1950e176bc59SStefano Zampini     } else {
1951e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1952e176bc59SStefano Zampini       is->cctx = is->rctx;
1953e176bc59SStefano Zampini     }
19543fd1c9e7SStefano Zampini 
19553fd1c9e7SStefano Zampini     /* interface counter vector (local) */
19563fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
19573fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
19583fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19593fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19603fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19613fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19623fd1c9e7SStefano Zampini 
19633fd1c9e7SStefano Zampini     /* free workspace */
1964e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1965e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
19666bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
19676bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1968f26d0771SStefano Zampini   }
196948ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1970b4319ba4SBarry Smith   PetscFunctionReturn(0);
1971b4319ba4SBarry Smith }
1972b4319ba4SBarry Smith 
1973a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
19742e74eeadSLisandro Dalcin {
19752e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
19762e74eeadSLisandro Dalcin   PetscErrorCode ierr;
197797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
197897563a80SStefano Zampini   PetscInt       i,zm,zn;
197997563a80SStefano Zampini #endif
1980f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
19812e74eeadSLisandro Dalcin 
19822e74eeadSLisandro Dalcin   PetscFunctionBegin;
19832e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1984f26d0771SStefano 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);
198597563a80SStefano Zampini   /* count negative indices */
198697563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
198797563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
19882e74eeadSLisandro Dalcin #endif
198997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
199097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
199197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
199297563a80SStefano Zampini   /* count negative indices (should be the same as before) */
199397563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
199497563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
1995b4f971dfSStefano Zampini   if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
1996b4f971dfSStefano Zampini   if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
199797563a80SStefano Zampini #endif
19982e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
19992e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20002e74eeadSLisandro Dalcin }
20012e74eeadSLisandro Dalcin 
2002a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
200397563a80SStefano Zampini {
200497563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
200597563a80SStefano Zampini   PetscErrorCode ierr;
200697563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
200797563a80SStefano Zampini   PetscInt       i,zm,zn;
200897563a80SStefano Zampini #endif
2009f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
201097563a80SStefano Zampini 
201197563a80SStefano Zampini   PetscFunctionBegin;
201297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
2013f26d0771SStefano 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);
201497563a80SStefano Zampini   /* count negative indices */
201597563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
201697563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
201797563a80SStefano Zampini #endif
201897563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
201997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
202097563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
202197563a80SStefano Zampini   /* count negative indices (should be the same as before) */
202297563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
202397563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2024b4f971dfSStefano Zampini   if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
2025b4f971dfSStefano Zampini   if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
202697563a80SStefano Zampini #endif
2027d59cf9ebSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
202897563a80SStefano Zampini   PetscFunctionReturn(0);
202997563a80SStefano Zampini }
203097563a80SStefano Zampini 
2031a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2032b4319ba4SBarry Smith {
2033dfbe8321SBarry Smith   PetscErrorCode ierr;
2034b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2035b4319ba4SBarry Smith 
2036b4319ba4SBarry Smith   PetscFunctionBegin;
2037b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2038872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2039872cf891SStefano Zampini   } else {
2040b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2041872cf891SStefano Zampini   }
2042b4319ba4SBarry Smith   PetscFunctionReturn(0);
2043b4319ba4SBarry Smith }
2044b4319ba4SBarry Smith 
2045a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2046f0006bf2SLisandro Dalcin {
2047f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
2048f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
2049f0006bf2SLisandro Dalcin 
2050f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2051b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2052b4f971dfSStefano Zampini #if defined(PETSC_USE_DEBUG)
2053b4f971dfSStefano Zampini     PetscInt ibs,bs;
2054b4f971dfSStefano Zampini 
2055b4f971dfSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
2056b4f971dfSStefano Zampini     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
2057b4f971dfSStefano Zampini     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
2058b4f971dfSStefano Zampini #endif
2059b4f971dfSStefano Zampini     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2060b4f971dfSStefano Zampini   } else {
2061f0006bf2SLisandro Dalcin     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2062b4f971dfSStefano Zampini   }
2063f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
2064f0006bf2SLisandro Dalcin }
2065f0006bf2SLisandro Dalcin 
2066f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2067f0ae7da4SStefano Zampini {
2068f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2069f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2070f0ae7da4SStefano Zampini 
2071f0ae7da4SStefano Zampini   PetscFunctionBegin;
2072f0ae7da4SStefano Zampini   if (!n) {
2073f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
2074f0ae7da4SStefano Zampini   } else {
2075f0ae7da4SStefano Zampini     PetscInt i;
2076f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
2077f0ae7da4SStefano Zampini 
2078f0ae7da4SStefano Zampini     if (columns) {
2079f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2080f0ae7da4SStefano Zampini     } else {
2081f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2082f0ae7da4SStefano Zampini     }
2083f0ae7da4SStefano Zampini     if (diag != 0.) {
2084f0ae7da4SStefano Zampini       const PetscScalar *array;
2085f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
2086f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
2087f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
2088f0ae7da4SStefano Zampini       }
2089f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
2090f0ae7da4SStefano Zampini     }
2091f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2092f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2093f0ae7da4SStefano Zampini   }
2094f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2095f0ae7da4SStefano Zampini }
2096f0ae7da4SStefano Zampini 
2097f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
20982e74eeadSLisandro Dalcin {
20996e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
21006e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
21016e520ac8SStefano Zampini   PetscInt       *lrows;
21022e74eeadSLisandro Dalcin   PetscErrorCode ierr;
21032e74eeadSLisandro Dalcin 
21042e74eeadSLisandro Dalcin   PetscFunctionBegin;
2105f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
2106f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
2107f0ae7da4SStefano Zampini     PetscBool cong;
210826b0207aSStefano Zampini 
2109f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
211026b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
2111268753edSStefano 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 and the l2g maps are the same for MATIS");
2112268753edSStefano 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 and the l2g maps are the same for MATIS");
2113268753edSStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent, and the l2g maps be the same");
2114f0ae7da4SStefano Zampini   }
2115f0ae7da4SStefano Zampini #endif
21166e520ac8SStefano Zampini   /* get locally owned rows */
2117f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
21186e520ac8SStefano Zampini   /* fix right hand side if needed */
21196e520ac8SStefano Zampini   if (x && b) {
21206e520ac8SStefano Zampini     const PetscScalar *xx;
21216e520ac8SStefano Zampini     PetscScalar       *bb;
21226e520ac8SStefano Zampini 
21236e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
21246e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
21256e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
21266e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
21276e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
21282e74eeadSLisandro Dalcin   }
21296e520ac8SStefano Zampini   /* get rows associated to the local matrices */
21303d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
21316e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
21326e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
21336e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
21346e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
21356e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
21366e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
21376e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
21386e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
21396e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
2140f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
21416e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
21422e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
21432e74eeadSLisandro Dalcin }
21442e74eeadSLisandro Dalcin 
2145f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2146b4319ba4SBarry Smith {
2147dfbe8321SBarry Smith   PetscErrorCode ierr;
2148b4319ba4SBarry Smith 
2149b4319ba4SBarry Smith   PetscFunctionBegin;
2150f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
2151f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2152f0ae7da4SStefano Zampini }
21532205254eSKarl Rupp 
2154f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2155f0ae7da4SStefano Zampini {
2156f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2157f0ae7da4SStefano Zampini 
2158f0ae7da4SStefano Zampini   PetscFunctionBegin;
2159f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
2160b4319ba4SBarry Smith   PetscFunctionReturn(0);
2161b4319ba4SBarry Smith }
2162b4319ba4SBarry Smith 
2163a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2164b4319ba4SBarry Smith {
2165b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2166dfbe8321SBarry Smith   PetscErrorCode ierr;
2167b4319ba4SBarry Smith 
2168b4319ba4SBarry Smith   PetscFunctionBegin;
2169b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
2170b4319ba4SBarry Smith   PetscFunctionReturn(0);
2171b4319ba4SBarry Smith }
2172b4319ba4SBarry Smith 
2173a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2174b4319ba4SBarry Smith {
2175b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2176dfbe8321SBarry Smith   PetscErrorCode ierr;
2177b4319ba4SBarry Smith 
2178b4319ba4SBarry Smith   PetscFunctionBegin;
2179b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
2180872cf891SStefano Zampini   /* fix for local empty rows/cols */
2181872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2182872cf891SStefano Zampini     Mat                    newlA;
2183872cf891SStefano Zampini     ISLocalToGlobalMapping l2g;
2184872cf891SStefano Zampini     IS                     tis;
2185872cf891SStefano Zampini     const PetscScalar      *v;
2186872cf891SStefano Zampini     PetscInt               i,n,cf,*loce,*locf;
2187872cf891SStefano Zampini     PetscBool              sym;
2188872cf891SStefano Zampini 
2189872cf891SStefano Zampini     ierr = MatGetRowMaxAbs(is->A,is->y,NULL);CHKERRQ(ierr);
2190872cf891SStefano Zampini     ierr = MatIsSymmetric(is->A,PETSC_SMALL,&sym);CHKERRQ(ierr);
2191872cf891SStefano Zampini     if (!sym) SETERRQ(PetscObjectComm((PetscObject)is->A),PETSC_ERR_SUP,"Not yet implemented for unsymmetric case");
2192872cf891SStefano Zampini     ierr = VecGetLocalSize(is->y,&n);CHKERRQ(ierr);
2193872cf891SStefano Zampini     ierr = PetscMalloc1(n,&loce);CHKERRQ(ierr);
2194872cf891SStefano Zampini     ierr = PetscMalloc1(n,&locf);CHKERRQ(ierr);
2195872cf891SStefano Zampini     ierr = VecGetArrayRead(is->y,&v);CHKERRQ(ierr);
2196872cf891SStefano Zampini     for (i=0,cf=0;i<n;i++) {
2197872cf891SStefano Zampini       if (v[i] == 0.0) {
2198872cf891SStefano Zampini         loce[i] = -1;
2199872cf891SStefano Zampini       } else {
2200872cf891SStefano Zampini         loce[i]    = cf;
2201872cf891SStefano Zampini         locf[cf++] = i;
2202872cf891SStefano Zampini       }
2203872cf891SStefano Zampini     }
2204872cf891SStefano Zampini     ierr = VecRestoreArrayRead(is->y,&v);CHKERRQ(ierr);
2205872cf891SStefano Zampini     /* extract valid submatrix */
2206872cf891SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A),cf,locf,PETSC_USE_POINTER,&tis);CHKERRQ(ierr);
2207e5b89577SStefano Zampini     ierr = MatCreateSubMatrix(is->A,tis,tis,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
2208872cf891SStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
2209872cf891SStefano Zampini     /* attach local l2g map for successive calls of MatSetValues */
2210872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is->A),1,n,loce,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
2211872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(newlA,l2g,l2g);CHKERRQ(ierr);
2212872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
2213872cf891SStefano Zampini     /* attach new global l2g map */
2214872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,cf,locf,locf);CHKERRQ(ierr);
2215872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,cf,locf,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
2216872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(A,l2g,l2g);CHKERRQ(ierr);
2217872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
2218872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
2219872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
2220872cf891SStefano Zampini   }
2221872cf891SStefano Zampini   is->locempty = PETSC_FALSE;
2222b4319ba4SBarry Smith   PetscFunctionReturn(0);
2223b4319ba4SBarry Smith }
2224b4319ba4SBarry Smith 
2225a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2226b4319ba4SBarry Smith {
2227b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
2228b4319ba4SBarry Smith 
2229b4319ba4SBarry Smith   PetscFunctionBegin;
2230b4319ba4SBarry Smith   *local = is->A;
2231b4319ba4SBarry Smith   PetscFunctionReturn(0);
2232b4319ba4SBarry Smith }
2233b4319ba4SBarry Smith 
22343b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
22353b3b1effSJed Brown {
22363b3b1effSJed Brown   PetscFunctionBegin;
22373b3b1effSJed Brown   *local = NULL;
22383b3b1effSJed Brown   PetscFunctionReturn(0);
22393b3b1effSJed Brown }
22403b3b1effSJed Brown 
2241b4319ba4SBarry Smith /*@
2242b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2243b4319ba4SBarry Smith 
2244b4319ba4SBarry Smith   Input Parameter:
2245b4319ba4SBarry Smith .  mat - the matrix
2246b4319ba4SBarry Smith 
2247b4319ba4SBarry Smith   Output Parameter:
2248eb82efa4SStefano Zampini .  local - the local matrix
2249b4319ba4SBarry Smith 
2250b4319ba4SBarry Smith   Level: advanced
2251b4319ba4SBarry Smith 
2252b4319ba4SBarry Smith   Notes:
2253b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
2254b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
2255b4319ba4SBarry Smith   of the MatSetValues() operation.
2256b4319ba4SBarry Smith 
22573b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
225896a6f129SJed Brown 
2259b4319ba4SBarry Smith .seealso: MATIS
2260b4319ba4SBarry Smith @*/
22617087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2262b4319ba4SBarry Smith {
22634ac538c5SBarry Smith   PetscErrorCode ierr;
2264b4319ba4SBarry Smith 
2265b4319ba4SBarry Smith   PetscFunctionBegin;
22660700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2267b4319ba4SBarry Smith   PetscValidPointer(local,2);
22684ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
2269b4319ba4SBarry Smith   PetscFunctionReturn(0);
2270b4319ba4SBarry Smith }
2271b4319ba4SBarry Smith 
22723b3b1effSJed Brown /*@
22733b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
22743b3b1effSJed Brown 
22753b3b1effSJed Brown   Input Parameter:
22763b3b1effSJed Brown .  mat - the matrix
22773b3b1effSJed Brown 
22783b3b1effSJed Brown   Output Parameter:
22793b3b1effSJed Brown .  local - the local matrix
22803b3b1effSJed Brown 
22813b3b1effSJed Brown   Level: advanced
22823b3b1effSJed Brown 
22833b3b1effSJed Brown .seealso: MATIS
22843b3b1effSJed Brown @*/
22853b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
22863b3b1effSJed Brown {
22873b3b1effSJed Brown   PetscErrorCode ierr;
22883b3b1effSJed Brown 
22893b3b1effSJed Brown   PetscFunctionBegin;
22903b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
22913b3b1effSJed Brown   PetscValidPointer(local,2);
22923b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
22933b3b1effSJed Brown   PetscFunctionReturn(0);
22943b3b1effSJed Brown }
22953b3b1effSJed Brown 
2296a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
22973b03a366Sstefano_zampini {
22983b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
22993b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
23003b03a366Sstefano_zampini   PetscErrorCode ierr;
23013b03a366Sstefano_zampini 
23023b03a366Sstefano_zampini   PetscFunctionBegin;
23034e4c7dbeSStefano Zampini   if (is->A) {
23043b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
23053b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2306f0ae7da4SStefano 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);
23074e4c7dbeSStefano Zampini   }
23083b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
23093b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
23103b03a366Sstefano_zampini   is->A = local;
23113b03a366Sstefano_zampini   PetscFunctionReturn(0);
23123b03a366Sstefano_zampini }
23133b03a366Sstefano_zampini 
23143b03a366Sstefano_zampini /*@
2315eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
23163b03a366Sstefano_zampini 
23173b03a366Sstefano_zampini   Input Parameter:
23183b03a366Sstefano_zampini .  mat - the matrix
2319eb82efa4SStefano Zampini .  local - the local matrix
23203b03a366Sstefano_zampini 
23213b03a366Sstefano_zampini   Output Parameter:
23223b03a366Sstefano_zampini 
23233b03a366Sstefano_zampini   Level: advanced
23243b03a366Sstefano_zampini 
23253b03a366Sstefano_zampini   Notes:
23263b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
23273b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
23283b03a366Sstefano_zampini 
23293b03a366Sstefano_zampini .seealso: MATIS
23303b03a366Sstefano_zampini @*/
23313b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
23323b03a366Sstefano_zampini {
23333b03a366Sstefano_zampini   PetscErrorCode ierr;
23343b03a366Sstefano_zampini 
23353b03a366Sstefano_zampini   PetscFunctionBegin;
23363b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2337b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
23383b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
23393b03a366Sstefano_zampini   PetscFunctionReturn(0);
23403b03a366Sstefano_zampini }
23413b03a366Sstefano_zampini 
2342a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
23436726f965SBarry Smith {
23446726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
23456726f965SBarry Smith   PetscErrorCode ierr;
23466726f965SBarry Smith 
23476726f965SBarry Smith   PetscFunctionBegin;
23486726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
23496726f965SBarry Smith   PetscFunctionReturn(0);
23506726f965SBarry Smith }
23516726f965SBarry Smith 
2352a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
23532e74eeadSLisandro Dalcin {
23542e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
23552e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23562e74eeadSLisandro Dalcin 
23572e74eeadSLisandro Dalcin   PetscFunctionBegin;
23582e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
23592e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23602e74eeadSLisandro Dalcin }
23612e74eeadSLisandro Dalcin 
2362a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
23632e74eeadSLisandro Dalcin {
23642e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
23652e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23662e74eeadSLisandro Dalcin 
23672e74eeadSLisandro Dalcin   PetscFunctionBegin;
23682e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
2369e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
23702e74eeadSLisandro Dalcin 
23712e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
23722e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
2373e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2374e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23752e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23762e74eeadSLisandro Dalcin }
23772e74eeadSLisandro Dalcin 
2378a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
23796726f965SBarry Smith {
23806726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
23816726f965SBarry Smith   PetscErrorCode ierr;
23826726f965SBarry Smith 
23836726f965SBarry Smith   PetscFunctionBegin;
23844e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
23856726f965SBarry Smith   PetscFunctionReturn(0);
23866726f965SBarry Smith }
23876726f965SBarry Smith 
2388f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
2389f26d0771SStefano Zampini {
2390f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
2391f26d0771SStefano Zampini   Mat_IS         *x;
2392f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2393f26d0771SStefano Zampini   PetscBool      ismatis;
2394f26d0771SStefano Zampini #endif
2395f26d0771SStefano Zampini   PetscErrorCode ierr;
2396f26d0771SStefano Zampini 
2397f26d0771SStefano Zampini   PetscFunctionBegin;
2398f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2399f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
2400f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
2401f26d0771SStefano Zampini #endif
2402f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
2403f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
2404f26d0771SStefano Zampini   PetscFunctionReturn(0);
2405f26d0771SStefano Zampini }
2406f26d0771SStefano Zampini 
2407f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
2408f26d0771SStefano Zampini {
2409f26d0771SStefano Zampini   Mat                    lA;
2410f26d0771SStefano Zampini   Mat_IS                 *matis;
2411f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2412f26d0771SStefano Zampini   IS                     is;
2413f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
2414f26d0771SStefano Zampini   PetscInt               nrg;
2415f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
2416f26d0771SStefano Zampini   PetscErrorCode         ierr;
2417f26d0771SStefano Zampini 
2418f26d0771SStefano Zampini   PetscFunctionBegin;
2419f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2420f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
2421f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
2422f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
2423f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2424f0ae7da4SStefano 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);
2425f26d0771SStefano Zampini #endif
2426f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
2427f26d0771SStefano Zampini   /* map from [0,nrl) to row */
2428f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
2429f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2430f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
2431f26d0771SStefano Zampini #else
2432f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
2433f26d0771SStefano Zampini #endif
2434f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
2435f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2436f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2437f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2438f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
2439f26d0771SStefano Zampini   /* compute new l2g map for columns */
2440f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2441f26d0771SStefano Zampini     const PetscInt *cg,*cl;
2442f26d0771SStefano Zampini     PetscInt       ncg;
2443f26d0771SStefano Zampini     PetscInt       ncl;
2444f26d0771SStefano Zampini 
2445f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2446f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2447f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2448f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2449f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2450f0ae7da4SStefano 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);
2451f26d0771SStefano Zampini #endif
2452f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2453f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2454f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2455f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2456f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2457f26d0771SStefano Zampini #else
2458f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2459f26d0771SStefano Zampini #endif
2460f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2461f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2462f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2463f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2464f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2465f26d0771SStefano Zampini   } else {
2466f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2467f26d0771SStefano Zampini     cl2g = rl2g;
2468f26d0771SStefano Zampini   }
2469f26d0771SStefano Zampini   /* create the MATIS submatrix */
2470f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2471f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2472f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2473f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2474b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2475f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2476f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2477f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2478f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2479f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2480f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2481f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2482f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2483f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2484f26d0771SStefano Zampini   /* remove unsupported ops */
2485f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2486f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2487f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2488f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2489f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2490f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2491f26d0771SStefano Zampini   PetscFunctionReturn(0);
2492f26d0771SStefano Zampini }
2493f26d0771SStefano Zampini 
2494872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
2495872cf891SStefano Zampini {
2496872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
2497872cf891SStefano Zampini   PetscErrorCode ierr;
2498872cf891SStefano Zampini 
2499872cf891SStefano Zampini   PetscFunctionBegin;
2500872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
2501872cf891SStefano Zampini   ierr = PetscObjectOptionsBegin((PetscObject)A);
2502872cf891SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns",NULL,a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
2503*75d48cdbSStefano Zampini   ierr = PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL);CHKERRQ(ierr);
2504872cf891SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
2505872cf891SStefano Zampini   PetscFunctionReturn(0);
2506872cf891SStefano Zampini }
2507872cf891SStefano Zampini 
2508284134d9SBarry Smith /*@
25093c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2510284134d9SBarry Smith        process but not across processes.
2511284134d9SBarry Smith 
2512284134d9SBarry Smith    Input Parameters:
2513284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2514e176bc59SStefano Zampini .     bs      - block size of the matrix
2515df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2516e176bc59SStefano Zampini .     rmap    - local to global map for rows
2517e176bc59SStefano Zampini -     cmap    - local to global map for cols
2518284134d9SBarry Smith 
2519284134d9SBarry Smith    Output Parameter:
2520284134d9SBarry Smith .    A - the resulting matrix
2521284134d9SBarry Smith 
25228e6c10adSSatish Balay    Level: advanced
25238e6c10adSSatish Balay 
252495452b02SPatrick Sanan    Notes:
252595452b02SPatrick Sanan     See MATIS for more details.
25266fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
25276fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
25283c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2529284134d9SBarry Smith 
2530284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2531284134d9SBarry Smith @*/
2532e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2533284134d9SBarry Smith {
2534284134d9SBarry Smith   PetscErrorCode ierr;
2535284134d9SBarry Smith 
2536284134d9SBarry Smith   PetscFunctionBegin;
25376fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2538284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2539284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
25406fdf41d1SStefano Zampini   if (bs > 0) {
2541284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
25426fdf41d1SStefano Zampini   }
2543284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2544e176bc59SStefano Zampini   if (rmap && cmap) {
2545e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2546e176bc59SStefano Zampini   } else if (!rmap) {
2547e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2548e176bc59SStefano Zampini   } else {
2549e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2550e176bc59SStefano Zampini   }
2551284134d9SBarry Smith   PetscFunctionReturn(0);
2552284134d9SBarry Smith }
2553284134d9SBarry Smith 
2554b4319ba4SBarry Smith /*MC
2555f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2556b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2557b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2558b4319ba4SBarry Smith    product is handled "implicitly".
2559b4319ba4SBarry Smith 
2560b4319ba4SBarry Smith    Operations Provided:
25616726f965SBarry Smith +  MatMult()
25622e74eeadSLisandro Dalcin .  MatMultAdd()
25632e74eeadSLisandro Dalcin .  MatMultTranspose()
25642e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
25656726f965SBarry Smith .  MatZeroEntries()
25666726f965SBarry Smith .  MatSetOption()
25672e74eeadSLisandro Dalcin .  MatZeroRows()
25682e74eeadSLisandro Dalcin .  MatSetValues()
256997563a80SStefano Zampini .  MatSetValuesBlocked()
25706726f965SBarry Smith .  MatSetValuesLocal()
257197563a80SStefano Zampini .  MatSetValuesBlockedLocal()
25722e74eeadSLisandro Dalcin .  MatScale()
25732e74eeadSLisandro Dalcin .  MatGetDiagonal()
25742b404112SStefano Zampini .  MatMissingDiagonal()
25752b404112SStefano Zampini .  MatDuplicate()
25762b404112SStefano Zampini .  MatCopy()
2577f26d0771SStefano Zampini .  MatAXPY()
25787dae84e0SHong Zhang .  MatCreateSubMatrix()
2579f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2580d7f69cd0SStefano Zampini .  MatTranspose()
2581*75d48cdbSStefano Zampini .  MatPtAP() (with P of AIJ type)
25826726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2583b4319ba4SBarry Smith 
2584b4319ba4SBarry Smith    Options Database Keys:
2585*75d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2586*75d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
2587*75d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
2588b4319ba4SBarry Smith 
258995452b02SPatrick Sanan    Notes:
259095452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
2591b4319ba4SBarry Smith 
2592b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2593b4319ba4SBarry Smith 
2594b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2595eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2596b4319ba4SBarry Smith 
2597b4319ba4SBarry Smith   Level: advanced
2598b4319ba4SBarry Smith 
2599f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2600b4319ba4SBarry Smith 
2601b4319ba4SBarry Smith M*/
2602b4319ba4SBarry Smith 
26038cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2604b4319ba4SBarry Smith {
2605dfbe8321SBarry Smith   PetscErrorCode ierr;
2606b4319ba4SBarry Smith   Mat_IS         *b;
2607b4319ba4SBarry Smith 
2608b4319ba4SBarry Smith   PetscFunctionBegin;
2609b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2610b4319ba4SBarry Smith   A->data = (void*)b;
2611b4319ba4SBarry Smith 
2612e176bc59SStefano Zampini   /* matrix ops */
2613e176bc59SStefano Zampini   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2614b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
26152e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
26162e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
26172e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2618b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2619b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
26202e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
262198921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2622b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2623f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
26242e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2625f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2626b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2627b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2628b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
26296726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
26302e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
26312e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
26326726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
263369796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
263469796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
263545471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2636ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
26376bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
26382b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2639659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
26407dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
2641f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
26423fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
26433fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2644d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
26457fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
2646ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
2647872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
2648b4319ba4SBarry Smith 
2649b7ce53b6SStefano Zampini   /* special MATIS functions */
2650bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
26513b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
2652bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2653b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
26542e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2655cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
2656*75d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS);CHKERRQ(ierr);
265717667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2658b4319ba4SBarry Smith   PetscFunctionReturn(0);
2659b4319ba4SBarry Smith }
2660