xref: /petsc/src/mat/impls/is/matis.c (revision 95452b02e12c0ee11232c7ff2b24b568a8e07e43)
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 
185b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
195b003df0Sstefano_zampini {
205b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
215b003df0Sstefano_zampini   PetscInt         i;
225b003df0Sstefano_zampini   PetscErrorCode   ierr;
235b003df0Sstefano_zampini 
24ab4d48faSStefano Zampini   PetscFunctionBegin;
255b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
265b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
275b003df0Sstefano_zampini   }
285b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
295b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
305b003df0Sstefano_zampini   }
315b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
325b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
335b003df0Sstefano_zampini   PetscFunctionReturn(0);
345b003df0Sstefano_zampini }
35a72627d2SStefano Zampini 
365b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyArray_Private(void *ptr)
377fa8f2d3SStefano Zampini {
386989cf23SStefano Zampini   PetscErrorCode ierr;
396989cf23SStefano Zampini 
406989cf23SStefano Zampini   PetscFunctionBeginUser;
416989cf23SStefano Zampini   ierr = PetscFree(ptr);CHKERRQ(ierr);
426989cf23SStefano Zampini   PetscFunctionReturn(0);
436989cf23SStefano Zampini }
446989cf23SStefano Zampini 
456989cf23SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
466989cf23SStefano Zampini {
476989cf23SStefano Zampini   Mat_MPIAIJ             *aij  = (Mat_MPIAIJ*)A->data;
486989cf23SStefano Zampini   Mat_SeqAIJ             *diag = (Mat_SeqAIJ*)(aij->A->data);
496989cf23SStefano Zampini   Mat_SeqAIJ             *offd = (Mat_SeqAIJ*)(aij->B->data);
506989cf23SStefano Zampini   Mat                    lA;
516989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
526989cf23SStefano Zampini   IS                     is;
536989cf23SStefano Zampini   MPI_Comm               comm;
546989cf23SStefano Zampini   void                   *ptrs[2];
556989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
566989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
576989cf23SStefano Zampini   PetscInt               *di,*dj,*oi,*oj;
586989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
59e363d98aSStefano Zampini   PetscInt               lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
606989cf23SStefano Zampini   PetscErrorCode         ierr;
616989cf23SStefano Zampini 
62ab4d48faSStefano Zampini   PetscFunctionBegin;
636989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
646989cf23SStefano Zampini   if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present");
656989cf23SStefano Zampini 
666989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
676989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
686989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
696989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
706989cf23SStefano Zampini   di   = diag->i;
716989cf23SStefano Zampini   dj   = diag->j;
726989cf23SStefano Zampini   dd   = diag->a;
736989cf23SStefano Zampini   oc   = aij->B->cmap->n;
746989cf23SStefano Zampini   oi   = offd->i;
756989cf23SStefano Zampini   oj   = offd->j;
766989cf23SStefano Zampini   od   = offd->a;
776989cf23SStefano Zampini   nnz  = diag->i[dr] + offd->i[dr];
786989cf23SStefano Zampini 
796989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
806989cf23SStefano Zampini   ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
816989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
826989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
83e363d98aSStefano Zampini   if (dr) {
846989cf23SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
856989cf23SStefano Zampini     for (i=0; i<dc; i++) aux[i]    = i+stc;
866989cf23SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i];
876989cf23SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
88e363d98aSStefano Zampini     lc   = dc+oc;
89e363d98aSStefano Zampini   } else {
90e363d98aSStefano Zampini     ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
91e363d98aSStefano Zampini     lc   = 0;
92e363d98aSStefano Zampini   }
936989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
946989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
956989cf23SStefano Zampini 
966989cf23SStefano Zampini   /* create MATIS object */
976989cf23SStefano Zampini   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
986989cf23SStefano Zampini   ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
996989cf23SStefano Zampini   ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1006989cf23SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1016989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1026989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1036989cf23SStefano Zampini 
1046989cf23SStefano Zampini   /* merge local matrices */
1056989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
1066989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
1076989cf23SStefano Zampini   ii   = aux;
1086989cf23SStefano Zampini   jj   = aux+dr+1;
1096989cf23SStefano Zampini   aa   = data;
1106989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
1116989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
1126989cf23SStefano Zampini   {
1136989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
1146989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
1156989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
1166989cf23SStefano Zampini   }
1176989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
1186989cf23SStefano Zampini   ii   = aux;
1196989cf23SStefano Zampini   jj   = aux+dr+1;
1206989cf23SStefano Zampini   aa   = data;
121e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
1226989cf23SStefano Zampini 
1236989cf23SStefano Zampini   /* create containers to destroy the data */
1246989cf23SStefano Zampini   ptrs[0] = aux;
1256989cf23SStefano Zampini   ptrs[1] = data;
1266989cf23SStefano Zampini   for (i=0; i<2; i++) {
1276989cf23SStefano Zampini     PetscContainer c;
1286989cf23SStefano Zampini 
1296989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
1306989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
1315b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyArray_Private);CHKERRQ(ierr);
1326989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
1336989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
1346989cf23SStefano Zampini   }
1356989cf23SStefano Zampini 
1366989cf23SStefano Zampini   /* finalize matrix */
1376989cf23SStefano Zampini   ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
1386989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
1396989cf23SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1406989cf23SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1416989cf23SStefano Zampini   PetscFunctionReturn(0);
1426989cf23SStefano Zampini }
1436989cf23SStefano Zampini 
144cf0a3239SStefano Zampini /*@
1453d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
146cf0a3239SStefano Zampini 
147cf0a3239SStefano Zampini    Collective on MPI_Comm
148cf0a3239SStefano Zampini 
149cf0a3239SStefano Zampini    Input Parameters:
150cf0a3239SStefano Zampini +  A - the matrix
151cf0a3239SStefano Zampini 
152cf0a3239SStefano Zampini    Level: advanced
153cf0a3239SStefano Zampini 
154*95452b02SPatrick Sanan    Notes:
155*95452b02SPatrick Sanan     This function does not need to be called by the user.
156cf0a3239SStefano Zampini 
157cf0a3239SStefano Zampini .keywords: matrix
158cf0a3239SStefano Zampini 
159cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
160cf0a3239SStefano Zampini @*/
161cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
162cf0a3239SStefano Zampini {
1637fa8f2d3SStefano Zampini   PetscErrorCode ierr;
1647fa8f2d3SStefano Zampini 
1657fa8f2d3SStefano Zampini   PetscFunctionBegin;
166cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
167cf0a3239SStefano Zampini   PetscValidType(A,1);
168cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
1697fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
1707fa8f2d3SStefano Zampini }
1717fa8f2d3SStefano Zampini 
1725e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1735e3038f0Sstefano_zampini {
1745e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
1755e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
1765e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
1775e3038f0Sstefano_zampini   MPI_Comm               comm;
1785b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
1795b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
1809e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
1815e3038f0Sstefano_zampini   PetscErrorCode         ierr;
1825e3038f0Sstefano_zampini 
183ab4d48faSStefano Zampini   PetscFunctionBegin;
1845e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
1855e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
1865e3038f0Sstefano_zampini   rnest  = NULL;
1875e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
1885e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
1895e3038f0Sstefano_zampini 
1905e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1915e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
1925e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
1935e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
1945e3038f0Sstefano_zampini     if (isnest) {
1955e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
1965e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
1975e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
1985e3038f0Sstefano_zampini     }
1995e3038f0Sstefano_zampini   }
2005e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
2015b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
2029e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
2035e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
2049e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
2055e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
2065e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2075e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2085e3038f0Sstefano_zampini       PetscBool ismatis;
2099e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
2105e3038f0Sstefano_zampini 
2115e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
2125e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2135e3038f0Sstefano_zampini 
2145e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
2159e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
2169e7b2b25Sstefano_zampini       if (istrans[ij]) {
2179e7b2b25Sstefano_zampini         Mat T,lT;
2189e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2199e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
2209e7b2b25Sstefano_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);
2219e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
2229e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
2239e7b2b25Sstefano_zampini       } else {
2245e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
2255e3038f0Sstefano_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);
2269e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
2279e7b2b25Sstefano_zampini       }
2285e3038f0Sstefano_zampini 
2295e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
2305e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
2319e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
2325e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
2335e3038f0Sstefano_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);
2345e3038f0Sstefano_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);
2355e3038f0Sstefano_zampini       lr[i] = l1;
2365e3038f0Sstefano_zampini       lc[j] = l2;
2375e3038f0Sstefano_zampini 
2385e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
2395e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
2405e3038f0Sstefano_zampini     }
2415e3038f0Sstefano_zampini   }
2425e3038f0Sstefano_zampini 
2435e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
2445e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
2455e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2465e3038f0Sstefano_zampini     rl2g = NULL;
2475e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2485e3038f0Sstefano_zampini       PetscInt n1,n2;
2495e3038f0Sstefano_zampini 
2505e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2519e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
2529e7b2b25Sstefano_zampini         Mat T;
2539e7b2b25Sstefano_zampini 
2549e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2559e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
2569e7b2b25Sstefano_zampini       } else {
2575e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
2589e7b2b25Sstefano_zampini       }
2595e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2605e3038f0Sstefano_zampini       if (!n1) continue;
2615e3038f0Sstefano_zampini       if (!rl2g) {
2625e3038f0Sstefano_zampini         rl2g = cl2g;
2635e3038f0Sstefano_zampini       } else {
2645e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2655e3038f0Sstefano_zampini         PetscBool      same;
2665e3038f0Sstefano_zampini 
2675e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2685e3038f0Sstefano_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);
2695e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2705e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2715e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2725e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2735e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2745e3038f0Sstefano_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);
2755e3038f0Sstefano_zampini       }
2765e3038f0Sstefano_zampini     }
2775e3038f0Sstefano_zampini   }
2785e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
2795e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
2805e3038f0Sstefano_zampini     rl2g = NULL;
2815e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
2825e3038f0Sstefano_zampini       PetscInt n1,n2;
2835e3038f0Sstefano_zampini 
2845e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
2859e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
2869e7b2b25Sstefano_zampini         Mat T;
2879e7b2b25Sstefano_zampini 
2889e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
2899e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
2909e7b2b25Sstefano_zampini       } else {
2915e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
2929e7b2b25Sstefano_zampini       }
2935e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2945e3038f0Sstefano_zampini       if (!n1) continue;
2955e3038f0Sstefano_zampini       if (!rl2g) {
2965e3038f0Sstefano_zampini         rl2g = cl2g;
2975e3038f0Sstefano_zampini       } else {
2985e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2995e3038f0Sstefano_zampini         PetscBool      same;
3005e3038f0Sstefano_zampini 
3015e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
3025e3038f0Sstefano_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);
3035e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
3045e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
3055e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
3065e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
3075e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
3085e3038f0Sstefano_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);
3095e3038f0Sstefano_zampini       }
3105e3038f0Sstefano_zampini     }
3115e3038f0Sstefano_zampini   }
3125e3038f0Sstefano_zampini #endif
3135e3038f0Sstefano_zampini 
3145e3038f0Sstefano_zampini   B = NULL;
3155e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
3165b003df0Sstefano_zampini     PetscInt stl;
3175b003df0Sstefano_zampini 
3185e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
3195e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
3205e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3215b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
3225e3038f0Sstefano_zampini       Mat            usedmat;
3235e3038f0Sstefano_zampini       Mat_IS         *matis;
3245e3038f0Sstefano_zampini       const PetscInt *idxs;
3255e3038f0Sstefano_zampini 
3265e3038f0Sstefano_zampini       /* local IS for local NEST */
3275b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
3285e3038f0Sstefano_zampini 
3295e3038f0Sstefano_zampini       /* l2gmap */
3305e3038f0Sstefano_zampini       j = 0;
3315e3038f0Sstefano_zampini       usedmat = nest[i][j];
3329e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
3339e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
3349e7b2b25Sstefano_zampini 
3359e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3369e7b2b25Sstefano_zampini         Mat T;
3379e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3389e7b2b25Sstefano_zampini         usedmat = T;
3399e7b2b25Sstefano_zampini       }
34082d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3415e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3425e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
3439e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3449e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3459e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3469e7b2b25Sstefano_zampini       } else {
3475e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3485e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3499e7b2b25Sstefano_zampini       }
3505e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
3515e3038f0Sstefano_zampini       stl += lr[i];
3525e3038f0Sstefano_zampini     }
3535e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
3545e3038f0Sstefano_zampini 
3555e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
3565e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
3575e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3585b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
3595e3038f0Sstefano_zampini       Mat            usedmat;
3605e3038f0Sstefano_zampini       Mat_IS         *matis;
3615e3038f0Sstefano_zampini       const PetscInt *idxs;
3625e3038f0Sstefano_zampini 
3635e3038f0Sstefano_zampini       /* local IS for local NEST */
3645b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
3655e3038f0Sstefano_zampini 
3665e3038f0Sstefano_zampini       /* l2gmap */
3675e3038f0Sstefano_zampini       j = 0;
3685e3038f0Sstefano_zampini       usedmat = nest[j][i];
3699e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
3709e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
3719e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3729e7b2b25Sstefano_zampini         Mat T;
3739e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3749e7b2b25Sstefano_zampini         usedmat = T;
3759e7b2b25Sstefano_zampini       }
37682d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3775e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3785e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
3799e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3809e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3819e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3829e7b2b25Sstefano_zampini       } else {
3835e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3845e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3859e7b2b25Sstefano_zampini       }
3865e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
3875e3038f0Sstefano_zampini       stl += lc[i];
3885e3038f0Sstefano_zampini     }
3895e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
3905e3038f0Sstefano_zampini 
3915e3038f0Sstefano_zampini     /* Create MATIS */
3925e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
3935e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
3945e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
3955e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
3965e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
3975e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
3985e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3995e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
4005e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
4019e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
4029e7b2b25Sstefano_zampini       if (istrans[i]) {
4039e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
4049e7b2b25Sstefano_zampini       }
4059e7b2b25Sstefano_zampini     }
4065e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
4075e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
4085e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4095e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4105e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
4115e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
4125e3038f0Sstefano_zampini     } else {
4135e3038f0Sstefano_zampini       *newmat = B;
4145e3038f0Sstefano_zampini     }
4155e3038f0Sstefano_zampini   } else {
4165e3038f0Sstefano_zampini     if (lreuse) {
4175e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4185e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
4195e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
4205e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
4215e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
4229e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
4239e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
4249e7b2b25Sstefano_zampini             }
4255e3038f0Sstefano_zampini           }
4265e3038f0Sstefano_zampini         }
4275e3038f0Sstefano_zampini       }
4285e3038f0Sstefano_zampini     } else {
4295b003df0Sstefano_zampini       PetscInt stl;
4305b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
4315b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
4325b003df0Sstefano_zampini         stl  += lr[i];
4335e3038f0Sstefano_zampini       }
4345b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
4355b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
4365b003df0Sstefano_zampini         stl  += lc[i];
4375e3038f0Sstefano_zampini       }
4385e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
439ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
4409e7b2b25Sstefano_zampini         if (istrans[i]) {
4419e7b2b25Sstefano_zampini           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
4429e7b2b25Sstefano_zampini         }
443ab4d48faSStefano Zampini       }
4445e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
4455e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
4465e3038f0Sstefano_zampini     }
4475e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4485e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4495e3038f0Sstefano_zampini   }
4505e3038f0Sstefano_zampini 
4515b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
4525b003df0Sstefano_zampini   convert = PETSC_FALSE;
4535b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
4545b003df0Sstefano_zampini   if (convert) {
4555b003df0Sstefano_zampini     Mat              M;
4565b003df0Sstefano_zampini     MatISLocalFields lf;
4575b003df0Sstefano_zampini     PetscContainer   c;
4585b003df0Sstefano_zampini 
4595b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4605b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
4615b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
4625b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
4635b003df0Sstefano_zampini 
4645b003df0Sstefano_zampini     /* attach local fields to the matrix */
4655b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
4665b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
4675b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
4685b003df0Sstefano_zampini       PetscInt n,st;
4695b003df0Sstefano_zampini 
4705b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
4715b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
4725b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
4735b003df0Sstefano_zampini     }
4745b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
4755b003df0Sstefano_zampini       PetscInt n,st;
4765b003df0Sstefano_zampini 
4775b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
4785b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
4795b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
4805b003df0Sstefano_zampini     }
4815b003df0Sstefano_zampini     lf->nr = nr;
4825b003df0Sstefano_zampini     lf->nc = nc;
4835b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
4845b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
4855b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
4865b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
4875b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
4885b003df0Sstefano_zampini   }
4895b003df0Sstefano_zampini 
4905e3038f0Sstefano_zampini   /* Free workspace */
4915e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4925e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
4935e3038f0Sstefano_zampini   }
4945e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
4955e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
4965e3038f0Sstefano_zampini   }
4979e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
4985b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
4995e3038f0Sstefano_zampini   PetscFunctionReturn(0);
5005e3038f0Sstefano_zampini }
5015e3038f0Sstefano_zampini 
502ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
503ad219c80Sstefano_zampini {
504ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
505ad219c80Sstefano_zampini   Vec               ll,rr;
506ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
507ad219c80Sstefano_zampini   PetscScalar       *x,*y;
508ad219c80Sstefano_zampini   PetscErrorCode    ierr;
509ad219c80Sstefano_zampini 
510ad219c80Sstefano_zampini   PetscFunctionBegin;
511ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
512ad219c80Sstefano_zampini   if (l) {
513ad219c80Sstefano_zampini     ll   = matis->y;
514ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
515ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
516ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
517ad219c80Sstefano_zampini   } else {
518ad219c80Sstefano_zampini     ll = NULL;
519ad219c80Sstefano_zampini   }
520ad219c80Sstefano_zampini   if (r) {
521ad219c80Sstefano_zampini     rr   = matis->x;
522ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
523ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
524ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
525ad219c80Sstefano_zampini   } else {
526ad219c80Sstefano_zampini     rr = NULL;
527ad219c80Sstefano_zampini   }
528ad219c80Sstefano_zampini   if (ll) {
529ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
530ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
531ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
532ad219c80Sstefano_zampini   }
533ad219c80Sstefano_zampini   if (rr) {
534ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
535ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
536ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
537ad219c80Sstefano_zampini   }
538ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
539ad219c80Sstefano_zampini   PetscFunctionReturn(0);
540ad219c80Sstefano_zampini }
541ad219c80Sstefano_zampini 
5427fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
5437fa8f2d3SStefano Zampini {
5447fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
5457fa8f2d3SStefano Zampini   MatInfo        info;
5467fa8f2d3SStefano Zampini   PetscReal      isend[6],irecv[6];
5477fa8f2d3SStefano Zampini   PetscInt       bs;
5487fa8f2d3SStefano Zampini   PetscErrorCode ierr;
5497fa8f2d3SStefano Zampini 
5507fa8f2d3SStefano Zampini   PetscFunctionBegin;
5517fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
5527fa8f2d3SStefano Zampini   if (matis->A->ops->getinfo) {
5537fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
5547fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
5557fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
5567fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
5577fa8f2d3SStefano Zampini     isend[3] = info.memory;
5587fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
5597fa8f2d3SStefano Zampini   } else {
5607fa8f2d3SStefano Zampini     isend[0] = 0.;
5617fa8f2d3SStefano Zampini     isend[1] = 0.;
5627fa8f2d3SStefano Zampini     isend[2] = 0.;
5637fa8f2d3SStefano Zampini     isend[3] = 0.;
5647fa8f2d3SStefano Zampini     isend[4] = 0.;
5657fa8f2d3SStefano Zampini   }
5667fa8f2d3SStefano Zampini   isend[5] = matis->A->num_ass;
5677fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
5687fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
5697fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
5707fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
5717fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
5727fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
5737fa8f2d3SStefano Zampini     ginfo->assemblies   = isend[5];
5747fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
5757fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
5767fa8f2d3SStefano Zampini 
5777fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
5787fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
5797fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
5807fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
5817fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
5827fa8f2d3SStefano Zampini     ginfo->assemblies   = irecv[5];
5837fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
5847fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
5857fa8f2d3SStefano Zampini 
5867fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
5877fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
5887fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
5897fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
5907fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
5917fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
592d7f69cd0SStefano Zampini   }
593d7f69cd0SStefano Zampini   ginfo->block_size        = bs;
594d7f69cd0SStefano Zampini   ginfo->fill_ratio_given  = 0;
595d7f69cd0SStefano Zampini   ginfo->fill_ratio_needed = 0;
596d7f69cd0SStefano Zampini   ginfo->factor_mallocs    = 0;
5975e3038f0Sstefano_zampini   PetscFunctionReturn(0);
5985e3038f0Sstefano_zampini }
5995e3038f0Sstefano_zampini 
600d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
601d7f69cd0SStefano Zampini {
602d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
603d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
604d7f69cd0SStefano Zampini 
605d7f69cd0SStefano Zampini   PetscFunctionBegin;
606cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
607cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
608d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
609d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
610d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
611d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
612d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
613d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
614cf37664fSBarry Smith   } else {
615cf37664fSBarry Smith     C = *B;
616d7f69cd0SStefano Zampini   }
617d7f69cd0SStefano Zampini 
618d7f69cd0SStefano Zampini   /* perform local transposition */
619d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
620d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
621d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
622d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
623d7f69cd0SStefano Zampini 
624cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
625d7f69cd0SStefano Zampini     *B = C;
626d7f69cd0SStefano Zampini   } else {
627d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
628d7f69cd0SStefano Zampini   }
6297aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6307aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
631d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
632d7f69cd0SStefano Zampini }
633d7f69cd0SStefano Zampini 
6343fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
6353fd1c9e7SStefano Zampini {
6363fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
6373fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6383fd1c9e7SStefano Zampini 
6393fd1c9e7SStefano Zampini   PetscFunctionBegin;
6404b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
6413fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6423fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6433fd1c9e7SStefano Zampini   }
6443fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
6453fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
6463fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6473fd1c9e7SStefano Zampini }
6483fd1c9e7SStefano Zampini 
6493fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
6503fd1c9e7SStefano Zampini {
6514b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
6523fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6533fd1c9e7SStefano Zampini 
6543fd1c9e7SStefano Zampini   PetscFunctionBegin;
6554b89b9cdSStefano Zampini   ierr = VecSet(is->y,a);CHKERRQ(ierr);
6563fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
6573fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6583fd1c9e7SStefano Zampini }
6593fd1c9e7SStefano Zampini 
660f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
661f26d0771SStefano Zampini {
662f26d0771SStefano Zampini   PetscErrorCode ierr;
663f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
664f26d0771SStefano Zampini 
665f26d0771SStefano Zampini   PetscFunctionBegin;
666f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
667f26d0771SStefano 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);
668f26d0771SStefano Zampini #endif
669f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
670f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
671b4f971dfSStefano Zampini   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
672f26d0771SStefano Zampini   PetscFunctionReturn(0);
673f26d0771SStefano Zampini }
674f26d0771SStefano Zampini 
675f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
676f26d0771SStefano Zampini {
677f26d0771SStefano Zampini   PetscErrorCode ierr;
678f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
679f26d0771SStefano Zampini 
680f26d0771SStefano Zampini   PetscFunctionBegin;
681f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
682f26d0771SStefano 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);
683f26d0771SStefano Zampini #endif
684f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
685f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
686b4f971dfSStefano Zampini   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
687f26d0771SStefano Zampini   PetscFunctionReturn(0);
688f26d0771SStefano Zampini }
689f26d0771SStefano Zampini 
690f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
691a8116848SStefano Zampini {
692a8116848SStefano Zampini   PetscInt      *owners = map->range;
693a8116848SStefano Zampini   PetscInt       n      = map->n;
694a8116848SStefano Zampini   PetscSF        sf;
695a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
696a8116848SStefano Zampini   PetscSFNode   *ridxs;
697a8116848SStefano Zampini   PetscMPIInt    rank;
698a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
699a8116848SStefano Zampini   PetscErrorCode ierr;
700a8116848SStefano Zampini 
701a8116848SStefano Zampini   PetscFunctionBegin;
702fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
703a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
704a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
705a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
706a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
707a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
708a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
709a8116848SStefano Zampini     const PetscInt idx = idxs[r];
710a8116848SStefano 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);
711a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
712a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
713a8116848SStefano Zampini     }
714a8116848SStefano Zampini     ridxs[r].rank = p;
715a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
716a8116848SStefano Zampini   }
717a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
718a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
719a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
720a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
721f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
722a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
723f0ae7da4SStefano Zampini 
724f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
725a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
726a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
727a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
728a8116848SStefano Zampini     start -= cum;
729a8116848SStefano Zampini     cum = 0;
730a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
731a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
732a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
733a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
734a8116848SStefano Zampini   }
735a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
736a8116848SStefano Zampini   /* Compress and put in indices */
737a8116848SStefano Zampini   for (r = 0; r < n; ++r)
738a8116848SStefano Zampini     if (lidxs[r] >= 0) {
739a8116848SStefano Zampini       if (work) work[len] = work[r];
740a8116848SStefano Zampini       lidxs[len++] = r;
741a8116848SStefano Zampini     }
742a8116848SStefano Zampini   if (on) *on = len;
743a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
744a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
745a8116848SStefano Zampini   PetscFunctionReturn(0);
746a8116848SStefano Zampini }
747a8116848SStefano Zampini 
7487dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
749a8116848SStefano Zampini {
750a8116848SStefano Zampini   Mat               locmat,newlocmat;
751a8116848SStefano Zampini   Mat_IS            *newmatis;
752a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
753a8116848SStefano Zampini   Vec               rtest,ltest;
754a8116848SStefano Zampini   const PetscScalar *array;
755a8116848SStefano Zampini #endif
756a8116848SStefano Zampini   const PetscInt    *idxs;
757a8116848SStefano Zampini   PetscInt          i,m,n;
758a8116848SStefano Zampini   PetscErrorCode    ierr;
759a8116848SStefano Zampini 
760a8116848SStefano Zampini   PetscFunctionBegin;
761a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
762a8116848SStefano Zampini     PetscBool ismatis;
763a8116848SStefano Zampini 
764a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
765a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
766a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
767a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
768a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
769a8116848SStefano Zampini   }
770a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
771a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
772a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
773a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
774a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
775a8116848SStefano Zampini   for (i=0;i<n;i++) {
776a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
777a8116848SStefano Zampini   }
778a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
779a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
780a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
781a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
782a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
783fd479f66SMatthew 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]));
784a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
785a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
786a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
787a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
788a8116848SStefano Zampini   for (i=0;i<n;i++) {
789a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
790a8116848SStefano Zampini   }
791a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
792a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
793a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
794a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
795a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
796fd479f66SMatthew 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]));
797a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
798a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
799a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
800a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
801a8116848SStefano Zampini #endif
802a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
803a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
804a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
805a8116848SStefano Zampini     IS                     is;
806a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
807306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
808a8116848SStefano Zampini     MPI_Comm               comm;
809a8116848SStefano Zampini 
810a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
811306cf5c7SStefano Zampini     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
812306cf5c7SStefano Zampini     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
813306cf5c7SStefano Zampini     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
814306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
815306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
816a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
817a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
818a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
819a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
820a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
821306cf5c7SStefano Zampini     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
822a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
823a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
824f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
825a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
8263d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
8273d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
828a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
829a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
830a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
831a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
832a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
8333d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
834a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
835a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8363d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
837a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
838a8116848SStefano Zampini         lidxs[newloc] = i;
839a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
840a8116848SStefano Zampini       }
841a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
842a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
843306cf5c7SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
844a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
845a8116848SStefano Zampini     /* local is to extract local submatrix */
846a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
847a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
848a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
849a8116848SStefano Zampini       PetscBool cong;
85026b0207aSStefano Zampini 
851a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
852a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
853a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
854a8116848SStefano Zampini     }
855268753edSStefano Zampini     if (mat->congruentlayouts && irow == icol && matis->csf == matis->sf) {
856a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
857a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
858a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
859a8116848SStefano Zampini     } else {
860a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
861a8116848SStefano Zampini 
862a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
863a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
864f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
865a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
8663d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
867a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
868a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
869a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
870a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
871a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
8723d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
873a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
874a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8753d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
876a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
877a8116848SStefano Zampini           lidxs[newloc] = i;
878a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
879a8116848SStefano Zampini         }
880a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
881a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
882306cf5c7SStefano Zampini       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
883a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
884a8116848SStefano Zampini       /* local is to extract local submatrix */
885a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
886a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
887a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
888a8116848SStefano Zampini     }
889a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
890a8116848SStefano Zampini   } else {
891a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
892a8116848SStefano Zampini   }
893a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
894a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
8957dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
896a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
897a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
898a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
899a8116848SStefano Zampini   }
900a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
901a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
902a8116848SStefano Zampini   PetscFunctionReturn(0);
903a8116848SStefano Zampini }
904a8116848SStefano Zampini 
905a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
9062b404112SStefano Zampini {
9072b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
9082b404112SStefano Zampini   PetscBool      ismatis;
9092b404112SStefano Zampini   PetscErrorCode ierr;
9102b404112SStefano Zampini 
9112b404112SStefano Zampini   PetscFunctionBegin;
9122b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
9132b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
9142b404112SStefano Zampini   b = (Mat_IS*)B->data;
9152b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
916cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
9172b404112SStefano Zampini   PetscFunctionReturn(0);
9182b404112SStefano Zampini }
9192b404112SStefano Zampini 
920a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
9216bd84002SStefano Zampini {
922527b2640SStefano Zampini   Vec               v;
923527b2640SStefano Zampini   const PetscScalar *array;
924527b2640SStefano Zampini   PetscInt          i,n;
9256bd84002SStefano Zampini   PetscErrorCode    ierr;
9266bd84002SStefano Zampini 
9276bd84002SStefano Zampini   PetscFunctionBegin;
928527b2640SStefano Zampini   *missing = PETSC_FALSE;
929527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
930527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
931527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
932527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
933527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
934527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
935527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
936527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
937527b2640SStefano Zampini   if (d) {
938527b2640SStefano Zampini     *d = -1;
939527b2640SStefano Zampini     if (*missing) {
940527b2640SStefano Zampini       PetscInt rstart;
941527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
942527b2640SStefano Zampini       *d = i+rstart;
943527b2640SStefano Zampini     }
944527b2640SStefano Zampini   }
9456bd84002SStefano Zampini   PetscFunctionReturn(0);
9466bd84002SStefano Zampini }
9476bd84002SStefano Zampini 
948cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
94928f4e0baSStefano Zampini {
95028f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
95128f4e0baSStefano Zampini   const PetscInt *gidxs;
9524f2d7cafSStefano Zampini   PetscInt       nleaves;
95328f4e0baSStefano Zampini   PetscErrorCode ierr;
95428f4e0baSStefano Zampini 
95528f4e0baSStefano Zampini   PetscFunctionBegin;
9564f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
95728f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
9583bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9594f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
9604f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
9613bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9624f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
963a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
9643d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
965a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
966a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9673d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
968a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9693d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
970a8116848SStefano Zampini   } else {
971a8116848SStefano Zampini     matis->csf = matis->sf;
972a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
973a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
974a8116848SStefano Zampini   }
97528f4e0baSStefano Zampini   PetscFunctionReturn(0);
97628f4e0baSStefano Zampini }
9772e1947a5SStefano Zampini 
978eb82efa4SStefano Zampini /*@
979a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
980a88811baSStefano Zampini 
981a88811baSStefano Zampini    Collective on MPI_Comm
982a88811baSStefano Zampini 
983a88811baSStefano Zampini    Input Parameters:
984a88811baSStefano Zampini +  B - the matrix
985a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
986a88811baSStefano Zampini            (same value is used for all local rows)
987a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
988a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
989a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
990a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
991a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
992a88811baSStefano Zampini            the diagonal entry even if it is zero.
993a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
994a88811baSStefano Zampini            submatrix (same value is used for all local rows).
995a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
996a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
997a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
998a88811baSStefano Zampini            structure. The size of this array is equal to the number
999a88811baSStefano Zampini            of local rows, i.e 'm'.
1000a88811baSStefano Zampini 
1001a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1002a88811baSStefano Zampini 
1003a88811baSStefano Zampini    Level: intermediate
1004a88811baSStefano Zampini 
1005*95452b02SPatrick Sanan    Notes:
1006*95452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1007a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1008a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1009a88811baSStefano Zampini 
1010a88811baSStefano Zampini .keywords: matrix
1011a88811baSStefano Zampini 
10123c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1013a88811baSStefano Zampini @*/
10142e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10152e1947a5SStefano Zampini {
10162e1947a5SStefano Zampini   PetscErrorCode ierr;
10172e1947a5SStefano Zampini 
10182e1947a5SStefano Zampini   PetscFunctionBegin;
10192e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
10202e1947a5SStefano Zampini   PetscValidType(B,1);
10212e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
10222e1947a5SStefano Zampini   PetscFunctionReturn(0);
10232e1947a5SStefano Zampini }
10242e1947a5SStefano Zampini 
10257230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10262e1947a5SStefano Zampini {
10272e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
102828f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
10292e1947a5SStefano Zampini   PetscErrorCode ierr;
10302e1947a5SStefano Zampini 
10312e1947a5SStefano Zampini   PetscFunctionBegin;
10326c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1033cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
10344f2d7cafSStefano Zampini 
10354f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
10364f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
10374f2d7cafSStefano Zampini 
10384f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
10394f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
10404f2d7cafSStefano Zampini 
104128f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
104228f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
104328f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
104428f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
10454f2d7cafSStefano Zampini 
10464f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
104728f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
10480f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
10490f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
10500f2f62c7SStefano Zampini #endif
10514f2d7cafSStefano Zampini 
10524f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
105328f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10544f2d7cafSStefano Zampini 
10554f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
105628f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10570f2f62c7SStefano Zampini 
10580f2f62c7SStefano Zampini   /* for other matrix types */
10590f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
10602e1947a5SStefano Zampini   PetscFunctionReturn(0);
10612e1947a5SStefano Zampini }
1062b4319ba4SBarry Smith 
10633927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
10643927de2eSStefano Zampini {
10653927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
10663927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1067ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
10683927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
10693927de2eSStefano Zampini   PetscInt        lrows,lcols;
10703927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
10713927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
10723927de2eSStefano Zampini   PetscBool       isdense,issbaij;
10733927de2eSStefano Zampini   PetscErrorCode  ierr;
10743927de2eSStefano Zampini 
10753927de2eSStefano Zampini   PetscFunctionBegin;
10763927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
10773927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
10783927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
10793927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
10803927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
10813927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1082ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1083ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
10847230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1085ecf5a873SStefano Zampini   } else {
1086ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1087ecf5a873SStefano Zampini   }
1088ecf5a873SStefano Zampini 
10893927de2eSStefano Zampini   if (issbaij) {
10903927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
10913927de2eSStefano Zampini   }
10923927de2eSStefano Zampini   /*
1093ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
10943927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
10953927de2eSStefano Zampini   */
1096cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
10973927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
10983927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
10993927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
11003927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
11013927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
11023927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
11033927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
11043927de2eSStefano Zampini       row_ownership[j] = i;
11053927de2eSStefano Zampini     }
11063927de2eSStefano Zampini   }
11077230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
11083927de2eSStefano Zampini 
11093927de2eSStefano Zampini   /*
11103927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
11113927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
11123927de2eSStefano Zampini   */
11133927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
11143927de2eSStefano Zampini   /* preallocation as a MATAIJ */
11153927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
11163927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
111712dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
111812dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1119ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
11203927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11213927de2eSStefano Zampini           my_dnz[i] += 1;
11223927de2eSStefano Zampini         } else { /* offdiag block */
11233927de2eSStefano Zampini           my_onz[i] += 1;
11243927de2eSStefano Zampini         }
11253927de2eSStefano Zampini       }
11263927de2eSStefano Zampini     }
1127bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1128bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1129bb1015c3SStefano Zampini     PetscBool      done;
1130bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1131938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1132bb1015c3SStefano Zampini     jptr = jj;
1133bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1134bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1135bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1136bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1137bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1138bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1139bb1015c3SStefano Zampini           my_dnz[i] += 1;
1140bb1015c3SStefano Zampini         } else { /* offdiag block */
1141bb1015c3SStefano Zampini           my_onz[i] += 1;
1142bb1015c3SStefano Zampini         }
1143bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1144bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1145bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1146bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1147bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1148bb1015c3SStefano Zampini           } else {
1149bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1150bb1015c3SStefano Zampini           }
1151bb1015c3SStefano Zampini         }
1152bb1015c3SStefano Zampini       }
1153bb1015c3SStefano Zampini     }
1154bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1155938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1156bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
11573927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
11583927de2eSStefano Zampini       const PetscInt *cols;
1159ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
11603927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11613927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
11623927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1163ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
11643927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11653927de2eSStefano Zampini           my_dnz[i] += 1;
11663927de2eSStefano Zampini         } else { /* offdiag block */
11673927de2eSStefano Zampini           my_onz[i] += 1;
11683927de2eSStefano Zampini         }
11693927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1170d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
11713927de2eSStefano Zampini           owner = row_ownership[index_col];
11723927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1173d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
11743927de2eSStefano Zampini           } else {
1175d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
11763927de2eSStefano Zampini           }
11773927de2eSStefano Zampini         }
11783927de2eSStefano Zampini       }
11793927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11803927de2eSStefano Zampini     }
11813927de2eSStefano Zampini   }
1182ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
11837230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1184ecf5a873SStefano Zampini   }
11854f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
11863927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1187ecf5a873SStefano Zampini 
1188ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
11893927de2eSStefano Zampini   if (maxreduce) {
11903927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11913927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1192bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11933927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
11943927de2eSStefano Zampini   } else {
11953927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
11963927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1197bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
11983927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
11993927de2eSStefano Zampini   }
12003927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
12013927de2eSStefano Zampini 
12023927de2eSStefano Zampini   /* Resize preallocation if overestimated */
12033927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
12043927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
12053927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
12063927de2eSStefano Zampini   }
12071670daf9Sstefano_zampini 
12081670daf9Sstefano_zampini   /* Set preallocation */
1209268753edSStefano Zampini   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
12103927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
12113927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
12123927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
12133927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
12143927de2eSStefano Zampini   }
1215268753edSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
12163927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12173927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12183927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
12193927de2eSStefano Zampini   if (issbaij) {
12203927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
12213927de2eSStefano Zampini   }
12223927de2eSStefano Zampini   PetscFunctionReturn(0);
12233927de2eSStefano Zampini }
12243927de2eSStefano Zampini 
12257230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1226b7ce53b6SStefano Zampini {
1227b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1228d9a9e74cSStefano Zampini   Mat            local_mat;
1229b7ce53b6SStefano Zampini   /* info on mat */
12303cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1231b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1232b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1233b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1234b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1235b9ed4604SStefano Zampini #endif
12367c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1237b7ce53b6SStefano Zampini   /* values insertion */
1238b7ce53b6SStefano Zampini   PetscScalar    *array;
1239b7ce53b6SStefano Zampini   /* work */
1240b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1241b7ce53b6SStefano Zampini 
1242b7ce53b6SStefano Zampini   PetscFunctionBegin;
1243b7ce53b6SStefano Zampini   /* get info from mat */
12447c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
12457c03b4e8SStefano Zampini   if (nsubdomains == 1) {
12461670daf9Sstefano_zampini     Mat            B;
12471670daf9Sstefano_zampini     IS             rows,cols;
1248acdf38a7Sstefano_zampini     IS             irows,icols;
12491670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
12501670daf9Sstefano_zampini 
12511670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
12521670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
12531670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
12541670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
1255acdf38a7Sstefano_zampini     ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1256acdf38a7Sstefano_zampini     ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1257acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr);
1258acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr);
1259268753edSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
1260268753edSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1261acdf38a7Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
1262acdf38a7Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
12636104e0f1Sstefano_zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
12647dae84e0SHong Zhang     ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1265acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1266acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1267acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
12687c03b4e8SStefano Zampini     PetscFunctionReturn(0);
12697c03b4e8SStefano Zampini   }
1270b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1271b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
12723cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1273b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1274b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
12754099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1276b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1277b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1278b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1279b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1280b9ed4604SStefano Zampini   lb[0] = isseqdense;
1281b9ed4604SStefano Zampini   lb[1] = isseqaij;
1282b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1283b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1284b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1285b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1286b9ed4604SStefano Zampini #endif
1287b7ce53b6SStefano Zampini 
1288b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
12893927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
12903cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
1291b9ed4604SStefano Zampini     if (!isseqsbaij) {
1292b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1293b9ed4604SStefano Zampini     } else {
1294b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1295b9ed4604SStefano Zampini     }
1296d59cf9ebSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
12973927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1298b7ce53b6SStefano Zampini   } else {
12993cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1300b7ce53b6SStefano Zampini     /* some checks */
1301b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1302b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
13033cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
13046c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
13056c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
13066c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
13076c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
13086c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1309b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1310b7ce53b6SStefano Zampini   }
1311d9a9e74cSStefano Zampini 
1312b9ed4604SStefano Zampini   if (isseqsbaij) {
1313d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1314d9a9e74cSStefano Zampini   } else {
1315d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1316d9a9e74cSStefano Zampini     local_mat = matis->A;
1317d9a9e74cSStefano Zampini   }
1318686e3a49SStefano Zampini 
1319b7ce53b6SStefano Zampini   /* Set values */
1320ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1321b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
132265066ba5SStefano Zampini     PetscInt i,*dummy;
1323ecf5a873SStefano Zampini 
132465066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
132565066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
1326b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1327d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
132865066ba5SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
1329d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
133065066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
1331686e3a49SStefano Zampini   } else if (isseqaij) {
1332ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1333686e3a49SStefano Zampini     PetscBool done;
1334686e3a49SStefano Zampini 
1335d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1336938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1337d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1338686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1339ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1340686e3a49SStefano Zampini     }
1341d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1342938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1343d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1344686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1345ecf5a873SStefano Zampini     PetscInt i;
1346c0962df8SStefano Zampini 
1347686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1348686e3a49SStefano Zampini       PetscInt       j;
1349ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1350686e3a49SStefano Zampini 
1351ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1352ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1353ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1354686e3a49SStefano Zampini     }
1355b7ce53b6SStefano Zampini   }
1356b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1357d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1358b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1359b9ed4604SStefano Zampini   if (isseqdense) {
1360b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1361b7ce53b6SStefano Zampini   }
1362b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1363b7ce53b6SStefano Zampini }
1364b7ce53b6SStefano Zampini 
1365b7ce53b6SStefano Zampini /*@
1366b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1367b7ce53b6SStefano Zampini 
1368b7ce53b6SStefano Zampini   Input Parameter:
1369b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1370b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1371b7ce53b6SStefano Zampini 
1372b7ce53b6SStefano Zampini   Output Parameter:
1373b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1374b7ce53b6SStefano Zampini 
1375b7ce53b6SStefano Zampini   Level: developer
1376b7ce53b6SStefano Zampini 
1377*95452b02SPatrick Sanan   Notes:
1378*95452b02SPatrick Sanan     mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1379b7ce53b6SStefano Zampini 
1380b7ce53b6SStefano Zampini .seealso: MATIS
1381b7ce53b6SStefano Zampini @*/
1382b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1383b7ce53b6SStefano Zampini {
1384b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1385b7ce53b6SStefano Zampini 
1386b7ce53b6SStefano Zampini   PetscFunctionBegin;
1387b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1388b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1389b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1390b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1391b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1392b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
13936c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1394b7ce53b6SStefano Zampini   }
1395b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1396b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1397b7ce53b6SStefano Zampini }
1398b7ce53b6SStefano Zampini 
1399ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1400ad6194a2SStefano Zampini {
1401ad6194a2SStefano Zampini   PetscErrorCode ierr;
1402ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1403ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1404ad6194a2SStefano Zampini   Mat            B,localmat;
1405ad6194a2SStefano Zampini 
1406ad6194a2SStefano Zampini   PetscFunctionBegin;
1407ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1408ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1409ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1410e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1411ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1412ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1413b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1414ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1415ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1416ad6194a2SStefano Zampini   *newmat = B;
1417ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1418ad6194a2SStefano Zampini }
1419ad6194a2SStefano Zampini 
1420a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
142169796d55SStefano Zampini {
142269796d55SStefano Zampini   PetscErrorCode ierr;
142369796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
142469796d55SStefano Zampini   PetscBool      local_sym;
142569796d55SStefano Zampini 
142669796d55SStefano Zampini   PetscFunctionBegin;
142769796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1428b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
142969796d55SStefano Zampini   PetscFunctionReturn(0);
143069796d55SStefano Zampini }
143169796d55SStefano Zampini 
1432a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
143369796d55SStefano Zampini {
143469796d55SStefano Zampini   PetscErrorCode ierr;
143569796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
143669796d55SStefano Zampini   PetscBool      local_sym;
143769796d55SStefano Zampini 
143869796d55SStefano Zampini   PetscFunctionBegin;
143969796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1440b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
144169796d55SStefano Zampini   PetscFunctionReturn(0);
144269796d55SStefano Zampini }
144369796d55SStefano Zampini 
144445471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
144545471136SStefano Zampini {
144645471136SStefano Zampini   PetscErrorCode ierr;
144745471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
144845471136SStefano Zampini   PetscBool      local_sym;
144945471136SStefano Zampini 
145045471136SStefano Zampini   PetscFunctionBegin;
145145471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
145245471136SStefano Zampini     *flg = PETSC_FALSE;
145345471136SStefano Zampini     PetscFunctionReturn(0);
145445471136SStefano Zampini   }
145545471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
145645471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
145745471136SStefano Zampini   PetscFunctionReturn(0);
145845471136SStefano Zampini }
145945471136SStefano Zampini 
1460a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1461b4319ba4SBarry Smith {
1462dfbe8321SBarry Smith   PetscErrorCode ierr;
1463b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1464b4319ba4SBarry Smith 
1465b4319ba4SBarry Smith   PetscFunctionBegin;
14666bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1467e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1468e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
14696bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
14706bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
14713fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1472a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1473a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1474a8116848SStefano Zampini   if (b->sf != b->csf) {
1475a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1476a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1477a8116848SStefano Zampini   }
147828f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
147928f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1480bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1481dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1482bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1483b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1484b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
14852e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1486cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1487b4319ba4SBarry Smith   PetscFunctionReturn(0);
1488b4319ba4SBarry Smith }
1489b4319ba4SBarry Smith 
1490a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1491b4319ba4SBarry Smith {
1492dfbe8321SBarry Smith   PetscErrorCode ierr;
1493b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1494b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1495b4319ba4SBarry Smith 
1496b4319ba4SBarry Smith   PetscFunctionBegin;
1497b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1498e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1499e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1500b4319ba4SBarry Smith 
1501b4319ba4SBarry Smith   /* multiply the local matrix */
1502b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1503b4319ba4SBarry Smith 
1504b4319ba4SBarry Smith   /* scatter product back into global memory */
15052dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1506e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1507e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1508b4319ba4SBarry Smith   PetscFunctionReturn(0);
1509b4319ba4SBarry Smith }
1510b4319ba4SBarry Smith 
1511a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15122e74eeadSLisandro Dalcin {
1513650997f4SStefano Zampini   Vec            temp_vec;
15142e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15152e74eeadSLisandro Dalcin 
15162e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1517650997f4SStefano Zampini   if (v3 != v2) {
1518650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1519650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1520650997f4SStefano Zampini   } else {
1521650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1522650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1523650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1524650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1525650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1526650997f4SStefano Zampini   }
15272e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15282e74eeadSLisandro Dalcin }
15292e74eeadSLisandro Dalcin 
1530a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
15312e74eeadSLisandro Dalcin {
15322e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
15332e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15342e74eeadSLisandro Dalcin 
1535e176bc59SStefano Zampini   PetscFunctionBegin;
15362e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1537e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1538e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15392e74eeadSLisandro Dalcin 
15402e74eeadSLisandro Dalcin   /* multiply the local matrix */
1541e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
15422e74eeadSLisandro Dalcin 
15432e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1544e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1545e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1546e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15472e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15482e74eeadSLisandro Dalcin }
15492e74eeadSLisandro Dalcin 
1550a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15512e74eeadSLisandro Dalcin {
1552650997f4SStefano Zampini   Vec            temp_vec;
15532e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15542e74eeadSLisandro Dalcin 
15552e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1556650997f4SStefano Zampini   if (v3 != v2) {
1557650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1558650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1559650997f4SStefano Zampini   } else {
1560650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1561650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1562650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1563650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1564650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1565650997f4SStefano Zampini   }
15662e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15672e74eeadSLisandro Dalcin }
15682e74eeadSLisandro Dalcin 
1569a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1570b4319ba4SBarry Smith {
1571b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1572dfbe8321SBarry Smith   PetscErrorCode ierr;
1573b4319ba4SBarry Smith   PetscViewer    sviewer;
1574ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1575b4319ba4SBarry Smith 
1576b4319ba4SBarry Smith   PetscFunctionBegin;
1577ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1578ee2491ecSStefano Zampini   if (isascii)  {
1579ee2491ecSStefano Zampini     PetscViewerFormat format;
1580ee2491ecSStefano Zampini 
1581ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1582ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1583ee2491ecSStefano Zampini   }
1584ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
15853f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1586b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
15873f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
15886e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1589b4319ba4SBarry Smith   PetscFunctionReturn(0);
1590b4319ba4SBarry Smith }
1591b4319ba4SBarry Smith 
1592a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1593b4319ba4SBarry Smith {
1594dfbe8321SBarry Smith   PetscErrorCode ierr;
1595e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1596b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1597b4319ba4SBarry Smith   IS             from,to;
1598e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1599b4319ba4SBarry Smith 
1600b4319ba4SBarry Smith   PetscFunctionBegin;
1601784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1602e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
16033bbff08aSStefano Zampini   /* Destroy any previous data */
160470cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
160570cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
16063fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1607e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1608e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
16091c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
1610872cf891SStefano Zampini   if (is->csf != is->sf) {
1611872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
1612872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
1613872cf891SStefano Zampini   }
161428f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
161528f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
16163bbff08aSStefano Zampini 
16173bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1618fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1619fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1620e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1621e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1622e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1623e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
16246625354bSStefano Zampini   /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */
16256625354bSStefano Zampini   if (rmapping != cmapping && A->rmap->N == A->cmap->N) {
16266625354bSStefano Zampini     PetscBool same,gsame;
16276625354bSStefano Zampini 
16286625354bSStefano Zampini     same = PETSC_FALSE;
16296625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
16306625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
16316625354bSStefano Zampini 
16326625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
16336625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
16346625354bSStefano Zampini       ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr);
16356625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
16366625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
16376625354bSStefano Zampini     }
16386625354bSStefano Zampini     ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
16396625354bSStefano Zampini     if (gsame) cmapping = rmapping;
16406625354bSStefano Zampini   }
16416625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
16426625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
16436625354bSStefano Zampini 
16446625354bSStefano Zampini   /* Create the local matrix A */
1645f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1646e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1647e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1648e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1649ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1650ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1651b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1652c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
1653c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
1654b4319ba4SBarry Smith 
1655f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1656b4319ba4SBarry Smith     /* Create the local work vectors */
16573bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1658b4319ba4SBarry Smith 
1659e176bc59SStefano Zampini     /* setup the global to local scatters */
1660e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1661e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1662784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1663e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1664e176bc59SStefano Zampini     if (rmapping != cmapping) {
1665e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1666e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1667e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1668e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1669e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1670e176bc59SStefano Zampini     } else {
1671e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1672e176bc59SStefano Zampini       is->cctx = is->rctx;
1673e176bc59SStefano Zampini     }
16743fd1c9e7SStefano Zampini 
16753fd1c9e7SStefano Zampini     /* interface counter vector (local) */
16763fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
16773fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
16783fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16793fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16803fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16813fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16823fd1c9e7SStefano Zampini 
16833fd1c9e7SStefano Zampini     /* free workspace */
1684e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1685e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
16866bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
16876bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1688f26d0771SStefano Zampini   }
168948ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1690b4319ba4SBarry Smith   PetscFunctionReturn(0);
1691b4319ba4SBarry Smith }
1692b4319ba4SBarry Smith 
1693a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
16942e74eeadSLisandro Dalcin {
16952e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
16962e74eeadSLisandro Dalcin   PetscErrorCode ierr;
169797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
169897563a80SStefano Zampini   PetscInt       i,zm,zn;
169997563a80SStefano Zampini #endif
1700f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
17012e74eeadSLisandro Dalcin 
17022e74eeadSLisandro Dalcin   PetscFunctionBegin;
17032e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1704f26d0771SStefano 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);
170597563a80SStefano Zampini   /* count negative indices */
170697563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
170797563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
17082e74eeadSLisandro Dalcin #endif
170997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
171097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
171197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
171297563a80SStefano Zampini   /* count negative indices (should be the same as before) */
171397563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
171497563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
1715b4f971dfSStefano 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");
1716b4f971dfSStefano 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");
171797563a80SStefano Zampini #endif
17182e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
17192e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
17202e74eeadSLisandro Dalcin }
17212e74eeadSLisandro Dalcin 
1722a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
172397563a80SStefano Zampini {
172497563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
172597563a80SStefano Zampini   PetscErrorCode ierr;
172697563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
172797563a80SStefano Zampini   PetscInt       i,zm,zn;
172897563a80SStefano Zampini #endif
1729f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
173097563a80SStefano Zampini 
173197563a80SStefano Zampini   PetscFunctionBegin;
173297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1733f26d0771SStefano 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);
173497563a80SStefano Zampini   /* count negative indices */
173597563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
173697563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
173797563a80SStefano Zampini #endif
173897563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
173997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
174097563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
174197563a80SStefano Zampini   /* count negative indices (should be the same as before) */
174297563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
174397563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
1744b4f971dfSStefano 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");
1745b4f971dfSStefano 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");
174697563a80SStefano Zampini #endif
1747d59cf9ebSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
174897563a80SStefano Zampini   PetscFunctionReturn(0);
174997563a80SStefano Zampini }
175097563a80SStefano Zampini 
1751a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1752b4319ba4SBarry Smith {
1753dfbe8321SBarry Smith   PetscErrorCode ierr;
1754b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1755b4319ba4SBarry Smith 
1756b4319ba4SBarry Smith   PetscFunctionBegin;
1757b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
1758872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1759872cf891SStefano Zampini   } else {
1760b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1761872cf891SStefano Zampini   }
1762b4319ba4SBarry Smith   PetscFunctionReturn(0);
1763b4319ba4SBarry Smith }
1764b4319ba4SBarry Smith 
1765a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1766f0006bf2SLisandro Dalcin {
1767f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1768f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1769f0006bf2SLisandro Dalcin 
1770f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1771b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
1772b4f971dfSStefano Zampini #if defined(PETSC_USE_DEBUG)
1773b4f971dfSStefano Zampini     PetscInt ibs,bs;
1774b4f971dfSStefano Zampini 
1775b4f971dfSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
1776b4f971dfSStefano Zampini     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
1777b4f971dfSStefano Zampini     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
1778b4f971dfSStefano Zampini #endif
1779b4f971dfSStefano Zampini     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1780b4f971dfSStefano Zampini   } else {
1781f0006bf2SLisandro Dalcin     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1782b4f971dfSStefano Zampini   }
1783f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1784f0006bf2SLisandro Dalcin }
1785f0006bf2SLisandro Dalcin 
1786f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1787f0ae7da4SStefano Zampini {
1788f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1789f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1790f0ae7da4SStefano Zampini 
1791f0ae7da4SStefano Zampini   PetscFunctionBegin;
1792f0ae7da4SStefano Zampini   if (!n) {
1793f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1794f0ae7da4SStefano Zampini   } else {
1795f0ae7da4SStefano Zampini     PetscInt i;
1796f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1797f0ae7da4SStefano Zampini 
1798f0ae7da4SStefano Zampini     if (columns) {
1799f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1800f0ae7da4SStefano Zampini     } else {
1801f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1802f0ae7da4SStefano Zampini     }
1803f0ae7da4SStefano Zampini     if (diag != 0.) {
1804f0ae7da4SStefano Zampini       const PetscScalar *array;
1805f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1806f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1807f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1808f0ae7da4SStefano Zampini       }
1809f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1810f0ae7da4SStefano Zampini     }
1811f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1812f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1813f0ae7da4SStefano Zampini   }
1814f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1815f0ae7da4SStefano Zampini }
1816f0ae7da4SStefano Zampini 
1817f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
18182e74eeadSLisandro Dalcin {
18196e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
18206e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
18216e520ac8SStefano Zampini   PetscInt       *lrows;
18222e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18232e74eeadSLisandro Dalcin 
18242e74eeadSLisandro Dalcin   PetscFunctionBegin;
1825f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1826f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1827f0ae7da4SStefano Zampini     PetscBool cong;
182826b0207aSStefano Zampini 
1829f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
183026b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
1831268753edSStefano 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");
1832268753edSStefano 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");
1833268753edSStefano 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");
1834f0ae7da4SStefano Zampini   }
1835f0ae7da4SStefano Zampini #endif
18366e520ac8SStefano Zampini   /* get locally owned rows */
1837f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
18386e520ac8SStefano Zampini   /* fix right hand side if needed */
18396e520ac8SStefano Zampini   if (x && b) {
18406e520ac8SStefano Zampini     const PetscScalar *xx;
18416e520ac8SStefano Zampini     PetscScalar       *bb;
18426e520ac8SStefano Zampini 
18436e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
18446e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
18456e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
18466e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
18476e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
18482e74eeadSLisandro Dalcin   }
18496e520ac8SStefano Zampini   /* get rows associated to the local matrices */
18503d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
18516e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
18526e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
18536e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
18546e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
18556e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18566e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18576e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18586e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
18596e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1860f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
18616e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18622e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18632e74eeadSLisandro Dalcin }
18642e74eeadSLisandro Dalcin 
1865f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1866b4319ba4SBarry Smith {
1867dfbe8321SBarry Smith   PetscErrorCode ierr;
1868b4319ba4SBarry Smith 
1869b4319ba4SBarry Smith   PetscFunctionBegin;
1870f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1871f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1872f0ae7da4SStefano Zampini }
18732205254eSKarl Rupp 
1874f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1875f0ae7da4SStefano Zampini {
1876f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1877f0ae7da4SStefano Zampini 
1878f0ae7da4SStefano Zampini   PetscFunctionBegin;
1879f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1880b4319ba4SBarry Smith   PetscFunctionReturn(0);
1881b4319ba4SBarry Smith }
1882b4319ba4SBarry Smith 
1883a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1884b4319ba4SBarry Smith {
1885b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1886dfbe8321SBarry Smith   PetscErrorCode ierr;
1887b4319ba4SBarry Smith 
1888b4319ba4SBarry Smith   PetscFunctionBegin;
1889b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1890b4319ba4SBarry Smith   PetscFunctionReturn(0);
1891b4319ba4SBarry Smith }
1892b4319ba4SBarry Smith 
1893a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1894b4319ba4SBarry Smith {
1895b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1896dfbe8321SBarry Smith   PetscErrorCode ierr;
1897b4319ba4SBarry Smith 
1898b4319ba4SBarry Smith   PetscFunctionBegin;
1899b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1900872cf891SStefano Zampini   /* fix for local empty rows/cols */
1901872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
1902872cf891SStefano Zampini     Mat                    newlA;
1903872cf891SStefano Zampini     ISLocalToGlobalMapping l2g;
1904872cf891SStefano Zampini     IS                     tis;
1905872cf891SStefano Zampini     const PetscScalar      *v;
1906872cf891SStefano Zampini     PetscInt               i,n,cf,*loce,*locf;
1907872cf891SStefano Zampini     PetscBool              sym;
1908872cf891SStefano Zampini 
1909872cf891SStefano Zampini     ierr = MatGetRowMaxAbs(is->A,is->y,NULL);CHKERRQ(ierr);
1910872cf891SStefano Zampini     ierr = MatIsSymmetric(is->A,PETSC_SMALL,&sym);CHKERRQ(ierr);
1911872cf891SStefano Zampini     if (!sym) SETERRQ(PetscObjectComm((PetscObject)is->A),PETSC_ERR_SUP,"Not yet implemented for unsymmetric case");
1912872cf891SStefano Zampini     ierr = VecGetLocalSize(is->y,&n);CHKERRQ(ierr);
1913872cf891SStefano Zampini     ierr = PetscMalloc1(n,&loce);CHKERRQ(ierr);
1914872cf891SStefano Zampini     ierr = PetscMalloc1(n,&locf);CHKERRQ(ierr);
1915872cf891SStefano Zampini     ierr = VecGetArrayRead(is->y,&v);CHKERRQ(ierr);
1916872cf891SStefano Zampini     for (i=0,cf=0;i<n;i++) {
1917872cf891SStefano Zampini       if (v[i] == 0.0) {
1918872cf891SStefano Zampini         loce[i] = -1;
1919872cf891SStefano Zampini       } else {
1920872cf891SStefano Zampini         loce[i]    = cf;
1921872cf891SStefano Zampini         locf[cf++] = i;
1922872cf891SStefano Zampini       }
1923872cf891SStefano Zampini     }
1924872cf891SStefano Zampini     ierr = VecRestoreArrayRead(is->y,&v);CHKERRQ(ierr);
1925872cf891SStefano Zampini     /* extract valid submatrix */
1926872cf891SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A),cf,locf,PETSC_USE_POINTER,&tis);CHKERRQ(ierr);
1927e5b89577SStefano Zampini     ierr = MatCreateSubMatrix(is->A,tis,tis,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
1928872cf891SStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
1929872cf891SStefano Zampini     /* attach local l2g map for successive calls of MatSetValues */
1930872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is->A),1,n,loce,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
1931872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(newlA,l2g,l2g);CHKERRQ(ierr);
1932872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
1933872cf891SStefano Zampini     /* attach new global l2g map */
1934872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,cf,locf,locf);CHKERRQ(ierr);
1935872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,cf,locf,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
1936872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(A,l2g,l2g);CHKERRQ(ierr);
1937872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
1938872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
1939872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
1940872cf891SStefano Zampini   }
1941872cf891SStefano Zampini   is->locempty = PETSC_FALSE;
1942b4319ba4SBarry Smith   PetscFunctionReturn(0);
1943b4319ba4SBarry Smith }
1944b4319ba4SBarry Smith 
1945a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1946b4319ba4SBarry Smith {
1947b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1948b4319ba4SBarry Smith 
1949b4319ba4SBarry Smith   PetscFunctionBegin;
1950b4319ba4SBarry Smith   *local = is->A;
1951b4319ba4SBarry Smith   PetscFunctionReturn(0);
1952b4319ba4SBarry Smith }
1953b4319ba4SBarry Smith 
19543b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
19553b3b1effSJed Brown {
19563b3b1effSJed Brown   PetscFunctionBegin;
19573b3b1effSJed Brown   *local = NULL;
19583b3b1effSJed Brown   PetscFunctionReturn(0);
19593b3b1effSJed Brown }
19603b3b1effSJed Brown 
1961b4319ba4SBarry Smith /*@
1962b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1963b4319ba4SBarry Smith 
1964b4319ba4SBarry Smith   Input Parameter:
1965b4319ba4SBarry Smith .  mat - the matrix
1966b4319ba4SBarry Smith 
1967b4319ba4SBarry Smith   Output Parameter:
1968eb82efa4SStefano Zampini .  local - the local matrix
1969b4319ba4SBarry Smith 
1970b4319ba4SBarry Smith   Level: advanced
1971b4319ba4SBarry Smith 
1972b4319ba4SBarry Smith   Notes:
1973b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1974b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1975b4319ba4SBarry Smith   of the MatSetValues() operation.
1976b4319ba4SBarry Smith 
19773b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
197896a6f129SJed Brown 
1979b4319ba4SBarry Smith .seealso: MATIS
1980b4319ba4SBarry Smith @*/
19817087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1982b4319ba4SBarry Smith {
19834ac538c5SBarry Smith   PetscErrorCode ierr;
1984b4319ba4SBarry Smith 
1985b4319ba4SBarry Smith   PetscFunctionBegin;
19860700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1987b4319ba4SBarry Smith   PetscValidPointer(local,2);
19884ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1989b4319ba4SBarry Smith   PetscFunctionReturn(0);
1990b4319ba4SBarry Smith }
1991b4319ba4SBarry Smith 
19923b3b1effSJed Brown /*@
19933b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
19943b3b1effSJed Brown 
19953b3b1effSJed Brown   Input Parameter:
19963b3b1effSJed Brown .  mat - the matrix
19973b3b1effSJed Brown 
19983b3b1effSJed Brown   Output Parameter:
19993b3b1effSJed Brown .  local - the local matrix
20003b3b1effSJed Brown 
20013b3b1effSJed Brown   Level: advanced
20023b3b1effSJed Brown 
20033b3b1effSJed Brown .seealso: MATIS
20043b3b1effSJed Brown @*/
20053b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
20063b3b1effSJed Brown {
20073b3b1effSJed Brown   PetscErrorCode ierr;
20083b3b1effSJed Brown 
20093b3b1effSJed Brown   PetscFunctionBegin;
20103b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
20113b3b1effSJed Brown   PetscValidPointer(local,2);
20123b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
20133b3b1effSJed Brown   PetscFunctionReturn(0);
20143b3b1effSJed Brown }
20153b3b1effSJed Brown 
2016a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
20173b03a366Sstefano_zampini {
20183b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
20193b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
20203b03a366Sstefano_zampini   PetscErrorCode ierr;
20213b03a366Sstefano_zampini 
20223b03a366Sstefano_zampini   PetscFunctionBegin;
20234e4c7dbeSStefano Zampini   if (is->A) {
20243b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
20253b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2026f0ae7da4SStefano 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);
20274e4c7dbeSStefano Zampini   }
20283b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
20293b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
20303b03a366Sstefano_zampini   is->A = local;
20313b03a366Sstefano_zampini   PetscFunctionReturn(0);
20323b03a366Sstefano_zampini }
20333b03a366Sstefano_zampini 
20343b03a366Sstefano_zampini /*@
2035eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
20363b03a366Sstefano_zampini 
20373b03a366Sstefano_zampini   Input Parameter:
20383b03a366Sstefano_zampini .  mat - the matrix
2039eb82efa4SStefano Zampini .  local - the local matrix
20403b03a366Sstefano_zampini 
20413b03a366Sstefano_zampini   Output Parameter:
20423b03a366Sstefano_zampini 
20433b03a366Sstefano_zampini   Level: advanced
20443b03a366Sstefano_zampini 
20453b03a366Sstefano_zampini   Notes:
20463b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
20473b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
20483b03a366Sstefano_zampini 
20493b03a366Sstefano_zampini .seealso: MATIS
20503b03a366Sstefano_zampini @*/
20513b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
20523b03a366Sstefano_zampini {
20533b03a366Sstefano_zampini   PetscErrorCode ierr;
20543b03a366Sstefano_zampini 
20553b03a366Sstefano_zampini   PetscFunctionBegin;
20563b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2057b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
20583b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
20593b03a366Sstefano_zampini   PetscFunctionReturn(0);
20603b03a366Sstefano_zampini }
20613b03a366Sstefano_zampini 
2062a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
20636726f965SBarry Smith {
20646726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
20656726f965SBarry Smith   PetscErrorCode ierr;
20666726f965SBarry Smith 
20676726f965SBarry Smith   PetscFunctionBegin;
20686726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
20696726f965SBarry Smith   PetscFunctionReturn(0);
20706726f965SBarry Smith }
20716726f965SBarry Smith 
2072a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
20732e74eeadSLisandro Dalcin {
20742e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20752e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20762e74eeadSLisandro Dalcin 
20772e74eeadSLisandro Dalcin   PetscFunctionBegin;
20782e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
20792e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20802e74eeadSLisandro Dalcin }
20812e74eeadSLisandro Dalcin 
2082a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
20832e74eeadSLisandro Dalcin {
20842e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20852e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20862e74eeadSLisandro Dalcin 
20872e74eeadSLisandro Dalcin   PetscFunctionBegin;
20882e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
2089e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
20902e74eeadSLisandro Dalcin 
20912e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
20922e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
2093e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2094e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20952e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20962e74eeadSLisandro Dalcin }
20972e74eeadSLisandro Dalcin 
2098a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
20996726f965SBarry Smith {
21006726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
21016726f965SBarry Smith   PetscErrorCode ierr;
21026726f965SBarry Smith 
21036726f965SBarry Smith   PetscFunctionBegin;
21044e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
21056726f965SBarry Smith   PetscFunctionReturn(0);
21066726f965SBarry Smith }
21076726f965SBarry Smith 
2108f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
2109f26d0771SStefano Zampini {
2110f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
2111f26d0771SStefano Zampini   Mat_IS         *x;
2112f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2113f26d0771SStefano Zampini   PetscBool      ismatis;
2114f26d0771SStefano Zampini #endif
2115f26d0771SStefano Zampini   PetscErrorCode ierr;
2116f26d0771SStefano Zampini 
2117f26d0771SStefano Zampini   PetscFunctionBegin;
2118f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2119f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
2120f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
2121f26d0771SStefano Zampini #endif
2122f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
2123f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
2124f26d0771SStefano Zampini   PetscFunctionReturn(0);
2125f26d0771SStefano Zampini }
2126f26d0771SStefano Zampini 
2127f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
2128f26d0771SStefano Zampini {
2129f26d0771SStefano Zampini   Mat                    lA;
2130f26d0771SStefano Zampini   Mat_IS                 *matis;
2131f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2132f26d0771SStefano Zampini   IS                     is;
2133f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
2134f26d0771SStefano Zampini   PetscInt               nrg;
2135f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
2136f26d0771SStefano Zampini   PetscErrorCode         ierr;
2137f26d0771SStefano Zampini 
2138f26d0771SStefano Zampini   PetscFunctionBegin;
2139f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2140f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
2141f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
2142f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
2143f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2144f0ae7da4SStefano 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);
2145f26d0771SStefano Zampini #endif
2146f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
2147f26d0771SStefano Zampini   /* map from [0,nrl) to row */
2148f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
2149f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2150f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
2151f26d0771SStefano Zampini #else
2152f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
2153f26d0771SStefano Zampini #endif
2154f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
2155f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2156f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2157f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2158f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
2159f26d0771SStefano Zampini   /* compute new l2g map for columns */
2160f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2161f26d0771SStefano Zampini     const PetscInt *cg,*cl;
2162f26d0771SStefano Zampini     PetscInt       ncg;
2163f26d0771SStefano Zampini     PetscInt       ncl;
2164f26d0771SStefano Zampini 
2165f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2166f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2167f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2168f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2169f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2170f0ae7da4SStefano 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);
2171f26d0771SStefano Zampini #endif
2172f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2173f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2174f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2175f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2176f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2177f26d0771SStefano Zampini #else
2178f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2179f26d0771SStefano Zampini #endif
2180f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2181f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2182f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2183f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2184f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2185f26d0771SStefano Zampini   } else {
2186f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2187f26d0771SStefano Zampini     cl2g = rl2g;
2188f26d0771SStefano Zampini   }
2189f26d0771SStefano Zampini   /* create the MATIS submatrix */
2190f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2191f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2192f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2193f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2194b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2195f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2196f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2197f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2198f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2199f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2200f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2201f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2202f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2203f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2204f26d0771SStefano Zampini   /* remove unsupported ops */
2205f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2206f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2207f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2208f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2209f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2210f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2211f26d0771SStefano Zampini   PetscFunctionReturn(0);
2212f26d0771SStefano Zampini }
2213f26d0771SStefano Zampini 
2214872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
2215872cf891SStefano Zampini {
2216872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
2217872cf891SStefano Zampini   PetscErrorCode ierr;
2218872cf891SStefano Zampini 
2219872cf891SStefano Zampini   PetscFunctionBegin;
2220872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
2221872cf891SStefano Zampini   ierr = PetscObjectOptionsBegin((PetscObject)A);
2222872cf891SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns",NULL,a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
2223872cf891SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
2224872cf891SStefano Zampini   PetscFunctionReturn(0);
2225872cf891SStefano Zampini }
2226872cf891SStefano Zampini 
2227284134d9SBarry Smith /*@
22283c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2229284134d9SBarry Smith        process but not across processes.
2230284134d9SBarry Smith 
2231284134d9SBarry Smith    Input Parameters:
2232284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2233e176bc59SStefano Zampini .     bs      - block size of the matrix
2234df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2235e176bc59SStefano Zampini .     rmap    - local to global map for rows
2236e176bc59SStefano Zampini -     cmap    - local to global map for cols
2237284134d9SBarry Smith 
2238284134d9SBarry Smith    Output Parameter:
2239284134d9SBarry Smith .    A - the resulting matrix
2240284134d9SBarry Smith 
22418e6c10adSSatish Balay    Level: advanced
22428e6c10adSSatish Balay 
2243*95452b02SPatrick Sanan    Notes:
2244*95452b02SPatrick Sanan     See MATIS for more details.
22456fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
22466fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
22473c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2248284134d9SBarry Smith 
2249284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2250284134d9SBarry Smith @*/
2251e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2252284134d9SBarry Smith {
2253284134d9SBarry Smith   PetscErrorCode ierr;
2254284134d9SBarry Smith 
2255284134d9SBarry Smith   PetscFunctionBegin;
22566fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2257284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2258284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
22596fdf41d1SStefano Zampini   if (bs > 0) {
2260284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
22616fdf41d1SStefano Zampini   }
2262284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2263e176bc59SStefano Zampini   if (rmap && cmap) {
2264e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2265e176bc59SStefano Zampini   } else if (!rmap) {
2266e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2267e176bc59SStefano Zampini   } else {
2268e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2269e176bc59SStefano Zampini   }
2270284134d9SBarry Smith   PetscFunctionReturn(0);
2271284134d9SBarry Smith }
2272284134d9SBarry Smith 
2273b4319ba4SBarry Smith /*MC
2274f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2275b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2276b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2277b4319ba4SBarry Smith    product is handled "implicitly".
2278b4319ba4SBarry Smith 
2279b4319ba4SBarry Smith    Operations Provided:
22806726f965SBarry Smith +  MatMult()
22812e74eeadSLisandro Dalcin .  MatMultAdd()
22822e74eeadSLisandro Dalcin .  MatMultTranspose()
22832e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
22846726f965SBarry Smith .  MatZeroEntries()
22856726f965SBarry Smith .  MatSetOption()
22862e74eeadSLisandro Dalcin .  MatZeroRows()
22872e74eeadSLisandro Dalcin .  MatSetValues()
228897563a80SStefano Zampini .  MatSetValuesBlocked()
22896726f965SBarry Smith .  MatSetValuesLocal()
229097563a80SStefano Zampini .  MatSetValuesBlockedLocal()
22912e74eeadSLisandro Dalcin .  MatScale()
22922e74eeadSLisandro Dalcin .  MatGetDiagonal()
22932b404112SStefano Zampini .  MatMissingDiagonal()
22942b404112SStefano Zampini .  MatDuplicate()
22952b404112SStefano Zampini .  MatCopy()
2296f26d0771SStefano Zampini .  MatAXPY()
22977dae84e0SHong Zhang .  MatCreateSubMatrix()
2298f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2299d7f69cd0SStefano Zampini .  MatTranspose()
23006726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2301b4319ba4SBarry Smith 
2302b4319ba4SBarry Smith    Options Database Keys:
2303b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2304b4319ba4SBarry Smith 
2305*95452b02SPatrick Sanan    Notes:
2306*95452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
2307b4319ba4SBarry Smith 
2308b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2309b4319ba4SBarry Smith 
2310b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2311eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2312b4319ba4SBarry Smith 
2313b4319ba4SBarry Smith   Level: advanced
2314b4319ba4SBarry Smith 
2315f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2316b4319ba4SBarry Smith 
2317b4319ba4SBarry Smith M*/
2318b4319ba4SBarry Smith 
23198cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2320b4319ba4SBarry Smith {
2321dfbe8321SBarry Smith   PetscErrorCode ierr;
2322b4319ba4SBarry Smith   Mat_IS         *b;
2323b4319ba4SBarry Smith 
2324b4319ba4SBarry Smith   PetscFunctionBegin;
2325b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2326b4319ba4SBarry Smith   A->data = (void*)b;
2327b4319ba4SBarry Smith 
2328e176bc59SStefano Zampini   /* matrix ops */
2329e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2330b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
23312e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
23322e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
23332e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2334b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2335b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
23362e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
233798921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2338b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2339f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
23402e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2341f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2342b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2343b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2344b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
23456726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
23462e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
23472e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
23486726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
234969796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
235069796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
235145471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2352ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
23536bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
23542b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2355659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
23567dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
2357f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
23583fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
23593fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2360d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
23617fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
2362ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
2363872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
2364b4319ba4SBarry Smith 
2365b7ce53b6SStefano Zampini   /* special MATIS functions */
2366bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
23673b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
2368bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2369b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
23702e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2371cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
237217667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2373b4319ba4SBarry Smith   PetscFunctionReturn(0);
2374b4319ba4SBarry Smith }
2375