xref: /petsc/src/mat/impls/is/matis.c (revision b81c21ee0929c5b35f910cc1b1eba6d4dfbc3180)
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 
366989cf23SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
376989cf23SStefano Zampini {
386989cf23SStefano Zampini   Mat_MPIAIJ             *aij  = (Mat_MPIAIJ*)A->data;
396989cf23SStefano Zampini   Mat_SeqAIJ             *diag = (Mat_SeqAIJ*)(aij->A->data);
406989cf23SStefano Zampini   Mat_SeqAIJ             *offd = (Mat_SeqAIJ*)(aij->B->data);
416989cf23SStefano Zampini   Mat                    lA;
426989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
436989cf23SStefano Zampini   IS                     is;
446989cf23SStefano Zampini   MPI_Comm               comm;
456989cf23SStefano Zampini   void                   *ptrs[2];
466989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
476989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
486989cf23SStefano Zampini   PetscInt               *di,*dj,*oi,*oj;
496989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
50e363d98aSStefano Zampini   PetscInt               lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
516989cf23SStefano Zampini   PetscErrorCode         ierr;
526989cf23SStefano Zampini 
53ab4d48faSStefano Zampini   PetscFunctionBegin;
546989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
556989cf23SStefano Zampini   if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present");
566989cf23SStefano Zampini 
576989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
586989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
596989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
606989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
616989cf23SStefano Zampini   di   = diag->i;
626989cf23SStefano Zampini   dj   = diag->j;
636989cf23SStefano Zampini   dd   = diag->a;
646989cf23SStefano Zampini   oc   = aij->B->cmap->n;
656989cf23SStefano Zampini   oi   = offd->i;
666989cf23SStefano Zampini   oj   = offd->j;
676989cf23SStefano Zampini   od   = offd->a;
686989cf23SStefano Zampini   nnz  = diag->i[dr] + offd->i[dr];
696989cf23SStefano Zampini 
706989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
716989cf23SStefano Zampini   ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
726989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
736989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
74e363d98aSStefano Zampini   if (dr) {
756989cf23SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
766989cf23SStefano Zampini     for (i=0; i<dc; i++) aux[i]    = i+stc;
776989cf23SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i];
786989cf23SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
79e363d98aSStefano Zampini     lc   = dc+oc;
80e363d98aSStefano Zampini   } else {
81e363d98aSStefano Zampini     ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
82e363d98aSStefano Zampini     lc   = 0;
83e363d98aSStefano Zampini   }
846989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
856989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
866989cf23SStefano Zampini 
876989cf23SStefano Zampini   /* create MATIS object */
886989cf23SStefano Zampini   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
896989cf23SStefano Zampini   ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
906989cf23SStefano Zampini   ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
916989cf23SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
926989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
936989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
946989cf23SStefano Zampini 
956989cf23SStefano Zampini   /* merge local matrices */
966989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
976989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
986989cf23SStefano Zampini   ii   = aux;
996989cf23SStefano Zampini   jj   = aux+dr+1;
1006989cf23SStefano Zampini   aa   = data;
1016989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
1026989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
1036989cf23SStefano Zampini   {
1046989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
1056989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
1066989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
1076989cf23SStefano Zampini   }
1086989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
1096989cf23SStefano Zampini   ii   = aux;
1106989cf23SStefano Zampini   jj   = aux+dr+1;
1116989cf23SStefano Zampini   aa   = data;
112e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
1136989cf23SStefano Zampini 
1146989cf23SStefano Zampini   /* create containers to destroy the data */
1156989cf23SStefano Zampini   ptrs[0] = aux;
1166989cf23SStefano Zampini   ptrs[1] = data;
1176989cf23SStefano Zampini   for (i=0; i<2; i++) {
1186989cf23SStefano Zampini     PetscContainer c;
1196989cf23SStefano Zampini 
1206989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
1216989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
122*b81c21eeSStefano Zampini     ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
1236989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
1246989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
1256989cf23SStefano Zampini   }
1266989cf23SStefano Zampini 
1276989cf23SStefano Zampini   /* finalize matrix */
1286989cf23SStefano Zampini   ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
1296989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
1306989cf23SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1316989cf23SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1326989cf23SStefano Zampini   PetscFunctionReturn(0);
1336989cf23SStefano Zampini }
1346989cf23SStefano Zampini 
135cf0a3239SStefano Zampini /*@
1363d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
137cf0a3239SStefano Zampini 
138cf0a3239SStefano Zampini    Collective on MPI_Comm
139cf0a3239SStefano Zampini 
140cf0a3239SStefano Zampini    Input Parameters:
141cf0a3239SStefano Zampini +  A - the matrix
142cf0a3239SStefano Zampini 
143cf0a3239SStefano Zampini    Level: advanced
144cf0a3239SStefano Zampini 
14595452b02SPatrick Sanan    Notes:
14695452b02SPatrick Sanan     This function does not need to be called by the user.
147cf0a3239SStefano Zampini 
148cf0a3239SStefano Zampini .keywords: matrix
149cf0a3239SStefano Zampini 
150cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
151cf0a3239SStefano Zampini @*/
152cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
153cf0a3239SStefano Zampini {
1547fa8f2d3SStefano Zampini   PetscErrorCode ierr;
1557fa8f2d3SStefano Zampini 
1567fa8f2d3SStefano Zampini   PetscFunctionBegin;
157cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
158cf0a3239SStefano Zampini   PetscValidType(A,1);
159cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
1607fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
1617fa8f2d3SStefano Zampini }
1627fa8f2d3SStefano Zampini 
1635e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1645e3038f0Sstefano_zampini {
1655e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
1665e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
1675e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
1685e3038f0Sstefano_zampini   MPI_Comm               comm;
1695b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
1705b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
1719e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
1725e3038f0Sstefano_zampini   PetscErrorCode         ierr;
1735e3038f0Sstefano_zampini 
174ab4d48faSStefano Zampini   PetscFunctionBegin;
1755e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
1765e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
1775e3038f0Sstefano_zampini   rnest  = NULL;
1785e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
1795e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
1805e3038f0Sstefano_zampini 
1815e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1825e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
1835e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
1845e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
1855e3038f0Sstefano_zampini     if (isnest) {
1865e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
1875e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
1885e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
1895e3038f0Sstefano_zampini     }
1905e3038f0Sstefano_zampini   }
1915e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1925b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
1939e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
1945e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
1959e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
1965e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
1975e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
1985e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
1995e3038f0Sstefano_zampini       PetscBool ismatis;
2009e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
2015e3038f0Sstefano_zampini 
2025e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
2035e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2045e3038f0Sstefano_zampini 
2055e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
2069e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
2079e7b2b25Sstefano_zampini       if (istrans[ij]) {
2089e7b2b25Sstefano_zampini         Mat T,lT;
2099e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2109e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
2119e7b2b25Sstefano_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);
2129e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
2139e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
2149e7b2b25Sstefano_zampini       } else {
2155e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
2165e3038f0Sstefano_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);
2179e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
2189e7b2b25Sstefano_zampini       }
2195e3038f0Sstefano_zampini 
2205e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
2215e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
2229e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
2235e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
2245e3038f0Sstefano_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);
2255e3038f0Sstefano_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);
2265e3038f0Sstefano_zampini       lr[i] = l1;
2275e3038f0Sstefano_zampini       lc[j] = l2;
2285e3038f0Sstefano_zampini 
2295e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
2305e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
2315e3038f0Sstefano_zampini     }
2325e3038f0Sstefano_zampini   }
2335e3038f0Sstefano_zampini 
2345e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
2355e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
2365e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2375e3038f0Sstefano_zampini     rl2g = NULL;
2385e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2395e3038f0Sstefano_zampini       PetscInt n1,n2;
2405e3038f0Sstefano_zampini 
2415e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2429e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
2439e7b2b25Sstefano_zampini         Mat T;
2449e7b2b25Sstefano_zampini 
2459e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2469e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
2479e7b2b25Sstefano_zampini       } else {
2485e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
2499e7b2b25Sstefano_zampini       }
2505e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2515e3038f0Sstefano_zampini       if (!n1) continue;
2525e3038f0Sstefano_zampini       if (!rl2g) {
2535e3038f0Sstefano_zampini         rl2g = cl2g;
2545e3038f0Sstefano_zampini       } else {
2555e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2565e3038f0Sstefano_zampini         PetscBool      same;
2575e3038f0Sstefano_zampini 
2585e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2595e3038f0Sstefano_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);
2605e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2615e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2625e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2635e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2645e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2655e3038f0Sstefano_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);
2665e3038f0Sstefano_zampini       }
2675e3038f0Sstefano_zampini     }
2685e3038f0Sstefano_zampini   }
2695e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
2705e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
2715e3038f0Sstefano_zampini     rl2g = NULL;
2725e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
2735e3038f0Sstefano_zampini       PetscInt n1,n2;
2745e3038f0Sstefano_zampini 
2755e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
2769e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
2779e7b2b25Sstefano_zampini         Mat T;
2789e7b2b25Sstefano_zampini 
2799e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
2809e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
2819e7b2b25Sstefano_zampini       } else {
2825e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
2839e7b2b25Sstefano_zampini       }
2845e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2855e3038f0Sstefano_zampini       if (!n1) continue;
2865e3038f0Sstefano_zampini       if (!rl2g) {
2875e3038f0Sstefano_zampini         rl2g = cl2g;
2885e3038f0Sstefano_zampini       } else {
2895e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2905e3038f0Sstefano_zampini         PetscBool      same;
2915e3038f0Sstefano_zampini 
2925e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2935e3038f0Sstefano_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);
2945e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2955e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2965e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2975e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2985e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2995e3038f0Sstefano_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);
3005e3038f0Sstefano_zampini       }
3015e3038f0Sstefano_zampini     }
3025e3038f0Sstefano_zampini   }
3035e3038f0Sstefano_zampini #endif
3045e3038f0Sstefano_zampini 
3055e3038f0Sstefano_zampini   B = NULL;
3065e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
3075b003df0Sstefano_zampini     PetscInt stl;
3085b003df0Sstefano_zampini 
3095e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
3105e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
3115e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3125b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
3135e3038f0Sstefano_zampini       Mat            usedmat;
3145e3038f0Sstefano_zampini       Mat_IS         *matis;
3155e3038f0Sstefano_zampini       const PetscInt *idxs;
3165e3038f0Sstefano_zampini 
3175e3038f0Sstefano_zampini       /* local IS for local NEST */
3185b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
3195e3038f0Sstefano_zampini 
3205e3038f0Sstefano_zampini       /* l2gmap */
3215e3038f0Sstefano_zampini       j = 0;
3225e3038f0Sstefano_zampini       usedmat = nest[i][j];
3239e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
3249e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
3259e7b2b25Sstefano_zampini 
3269e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3279e7b2b25Sstefano_zampini         Mat T;
3289e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3299e7b2b25Sstefano_zampini         usedmat = T;
3309e7b2b25Sstefano_zampini       }
33182d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3325e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3335e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
3349e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3359e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3369e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3379e7b2b25Sstefano_zampini       } else {
3385e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3395e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3409e7b2b25Sstefano_zampini       }
3415e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
3425e3038f0Sstefano_zampini       stl += lr[i];
3435e3038f0Sstefano_zampini     }
3445e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
3455e3038f0Sstefano_zampini 
3465e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
3475e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
3485e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3495b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
3505e3038f0Sstefano_zampini       Mat            usedmat;
3515e3038f0Sstefano_zampini       Mat_IS         *matis;
3525e3038f0Sstefano_zampini       const PetscInt *idxs;
3535e3038f0Sstefano_zampini 
3545e3038f0Sstefano_zampini       /* local IS for local NEST */
3555b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
3565e3038f0Sstefano_zampini 
3575e3038f0Sstefano_zampini       /* l2gmap */
3585e3038f0Sstefano_zampini       j = 0;
3595e3038f0Sstefano_zampini       usedmat = nest[j][i];
3609e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
3619e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
3629e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3639e7b2b25Sstefano_zampini         Mat T;
3649e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3659e7b2b25Sstefano_zampini         usedmat = T;
3669e7b2b25Sstefano_zampini       }
36782d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3685e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3695e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
3709e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3719e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3729e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3739e7b2b25Sstefano_zampini       } else {
3745e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3755e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3769e7b2b25Sstefano_zampini       }
3775e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
3785e3038f0Sstefano_zampini       stl += lc[i];
3795e3038f0Sstefano_zampini     }
3805e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
3815e3038f0Sstefano_zampini 
3825e3038f0Sstefano_zampini     /* Create MATIS */
3835e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
3845e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
3855e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
3865e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
3875e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
3885e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
3895e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3905e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3915e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
3929e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
3939e7b2b25Sstefano_zampini       if (istrans[i]) {
3949e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
3959e7b2b25Sstefano_zampini       }
3969e7b2b25Sstefano_zampini     }
3975e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
3985e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
3995e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4005e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4015e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
4025e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
4035e3038f0Sstefano_zampini     } else {
4045e3038f0Sstefano_zampini       *newmat = B;
4055e3038f0Sstefano_zampini     }
4065e3038f0Sstefano_zampini   } else {
4075e3038f0Sstefano_zampini     if (lreuse) {
4085e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4095e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
4105e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
4115e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
4125e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
4139e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
4149e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
4159e7b2b25Sstefano_zampini             }
4165e3038f0Sstefano_zampini           }
4175e3038f0Sstefano_zampini         }
4185e3038f0Sstefano_zampini       }
4195e3038f0Sstefano_zampini     } else {
4205b003df0Sstefano_zampini       PetscInt stl;
4215b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
4225b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
4235b003df0Sstefano_zampini         stl  += lr[i];
4245e3038f0Sstefano_zampini       }
4255b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
4265b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
4275b003df0Sstefano_zampini         stl  += lc[i];
4285e3038f0Sstefano_zampini       }
4295e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
430ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
4319e7b2b25Sstefano_zampini         if (istrans[i]) {
4329e7b2b25Sstefano_zampini           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
4339e7b2b25Sstefano_zampini         }
434ab4d48faSStefano Zampini       }
4355e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
4365e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
4375e3038f0Sstefano_zampini     }
4385e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4395e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4405e3038f0Sstefano_zampini   }
4415e3038f0Sstefano_zampini 
4425b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
4435b003df0Sstefano_zampini   convert = PETSC_FALSE;
4445b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
4455b003df0Sstefano_zampini   if (convert) {
4465b003df0Sstefano_zampini     Mat              M;
4475b003df0Sstefano_zampini     MatISLocalFields lf;
4485b003df0Sstefano_zampini     PetscContainer   c;
4495b003df0Sstefano_zampini 
4505b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4515b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
4525b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
4535b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
4545b003df0Sstefano_zampini 
4555b003df0Sstefano_zampini     /* attach local fields to the matrix */
4565b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
4575b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
4585b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
4595b003df0Sstefano_zampini       PetscInt n,st;
4605b003df0Sstefano_zampini 
4615b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
4625b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
4635b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
4645b003df0Sstefano_zampini     }
4655b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
4665b003df0Sstefano_zampini       PetscInt n,st;
4675b003df0Sstefano_zampini 
4685b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
4695b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
4705b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
4715b003df0Sstefano_zampini     }
4725b003df0Sstefano_zampini     lf->nr = nr;
4735b003df0Sstefano_zampini     lf->nc = nc;
4745b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
4755b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
4765b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
4775b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
4785b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
4795b003df0Sstefano_zampini   }
4805b003df0Sstefano_zampini 
4815e3038f0Sstefano_zampini   /* Free workspace */
4825e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4835e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
4845e3038f0Sstefano_zampini   }
4855e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
4865e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
4875e3038f0Sstefano_zampini   }
4889e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
4895b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
4905e3038f0Sstefano_zampini   PetscFunctionReturn(0);
4915e3038f0Sstefano_zampini }
4925e3038f0Sstefano_zampini 
493ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
494ad219c80Sstefano_zampini {
495ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
496ad219c80Sstefano_zampini   Vec               ll,rr;
497ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
498ad219c80Sstefano_zampini   PetscScalar       *x,*y;
499ad219c80Sstefano_zampini   PetscErrorCode    ierr;
500ad219c80Sstefano_zampini 
501ad219c80Sstefano_zampini   PetscFunctionBegin;
502ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
503ad219c80Sstefano_zampini   if (l) {
504ad219c80Sstefano_zampini     ll   = matis->y;
505ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
506ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
507ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
508ad219c80Sstefano_zampini   } else {
509ad219c80Sstefano_zampini     ll = NULL;
510ad219c80Sstefano_zampini   }
511ad219c80Sstefano_zampini   if (r) {
512ad219c80Sstefano_zampini     rr   = matis->x;
513ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
514ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
515ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
516ad219c80Sstefano_zampini   } else {
517ad219c80Sstefano_zampini     rr = NULL;
518ad219c80Sstefano_zampini   }
519ad219c80Sstefano_zampini   if (ll) {
520ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
521ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
522ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
523ad219c80Sstefano_zampini   }
524ad219c80Sstefano_zampini   if (rr) {
525ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
526ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
527ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
528ad219c80Sstefano_zampini   }
529ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
530ad219c80Sstefano_zampini   PetscFunctionReturn(0);
531ad219c80Sstefano_zampini }
532ad219c80Sstefano_zampini 
5337fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
5347fa8f2d3SStefano Zampini {
5357fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
5367fa8f2d3SStefano Zampini   MatInfo        info;
5377fa8f2d3SStefano Zampini   PetscReal      isend[6],irecv[6];
5387fa8f2d3SStefano Zampini   PetscInt       bs;
5397fa8f2d3SStefano Zampini   PetscErrorCode ierr;
5407fa8f2d3SStefano Zampini 
5417fa8f2d3SStefano Zampini   PetscFunctionBegin;
5427fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
5437fa8f2d3SStefano Zampini   if (matis->A->ops->getinfo) {
5447fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
5457fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
5467fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
5477fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
5487fa8f2d3SStefano Zampini     isend[3] = info.memory;
5497fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
5507fa8f2d3SStefano Zampini   } else {
5517fa8f2d3SStefano Zampini     isend[0] = 0.;
5527fa8f2d3SStefano Zampini     isend[1] = 0.;
5537fa8f2d3SStefano Zampini     isend[2] = 0.;
5547fa8f2d3SStefano Zampini     isend[3] = 0.;
5557fa8f2d3SStefano Zampini     isend[4] = 0.;
5567fa8f2d3SStefano Zampini   }
5577fa8f2d3SStefano Zampini   isend[5] = matis->A->num_ass;
5587fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
5597fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
5607fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
5617fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
5627fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
5637fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
5647fa8f2d3SStefano Zampini     ginfo->assemblies   = isend[5];
5657fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
5667fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
5677fa8f2d3SStefano Zampini 
5687fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
5697fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
5707fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
5717fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
5727fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
5737fa8f2d3SStefano Zampini     ginfo->assemblies   = irecv[5];
5747fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
5757fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,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   = A->num_ass;
583d7f69cd0SStefano Zampini   }
584d7f69cd0SStefano Zampini   ginfo->block_size        = bs;
585d7f69cd0SStefano Zampini   ginfo->fill_ratio_given  = 0;
586d7f69cd0SStefano Zampini   ginfo->fill_ratio_needed = 0;
587d7f69cd0SStefano Zampini   ginfo->factor_mallocs    = 0;
5885e3038f0Sstefano_zampini   PetscFunctionReturn(0);
5895e3038f0Sstefano_zampini }
5905e3038f0Sstefano_zampini 
591d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
592d7f69cd0SStefano Zampini {
593d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
594d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
595d7f69cd0SStefano Zampini 
596d7f69cd0SStefano Zampini   PetscFunctionBegin;
597cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
598cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
599d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
600d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
601d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
602d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
603d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
604d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
605cf37664fSBarry Smith   } else {
606cf37664fSBarry Smith     C = *B;
607d7f69cd0SStefano Zampini   }
608d7f69cd0SStefano Zampini 
609d7f69cd0SStefano Zampini   /* perform local transposition */
610d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
611d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
612d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
613d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
614d7f69cd0SStefano Zampini 
615cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
616d7f69cd0SStefano Zampini     *B = C;
617d7f69cd0SStefano Zampini   } else {
618d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
619d7f69cd0SStefano Zampini   }
6207aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6217aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
622d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
623d7f69cd0SStefano Zampini }
624d7f69cd0SStefano Zampini 
6253fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
6263fd1c9e7SStefano Zampini {
6273fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
6283fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6293fd1c9e7SStefano Zampini 
6303fd1c9e7SStefano Zampini   PetscFunctionBegin;
6314b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
6323fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6333fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6343fd1c9e7SStefano Zampini   }
6353fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
6363fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
6373fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6383fd1c9e7SStefano Zampini }
6393fd1c9e7SStefano Zampini 
6403fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
6413fd1c9e7SStefano Zampini {
6424b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
6433fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6443fd1c9e7SStefano Zampini 
6453fd1c9e7SStefano Zampini   PetscFunctionBegin;
6464b89b9cdSStefano Zampini   ierr = VecSet(is->y,a);CHKERRQ(ierr);
6473fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
6483fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6493fd1c9e7SStefano Zampini }
6503fd1c9e7SStefano Zampini 
651f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
652f26d0771SStefano Zampini {
653f26d0771SStefano Zampini   PetscErrorCode ierr;
654f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
655f26d0771SStefano Zampini 
656f26d0771SStefano Zampini   PetscFunctionBegin;
657f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
658f26d0771SStefano 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);
659f26d0771SStefano Zampini #endif
660f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
661f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
662b4f971dfSStefano Zampini   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
663f26d0771SStefano Zampini   PetscFunctionReturn(0);
664f26d0771SStefano Zampini }
665f26d0771SStefano Zampini 
666f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
667f26d0771SStefano Zampini {
668f26d0771SStefano Zampini   PetscErrorCode ierr;
669f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
670f26d0771SStefano Zampini 
671f26d0771SStefano Zampini   PetscFunctionBegin;
672f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
673f26d0771SStefano 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);
674f26d0771SStefano Zampini #endif
675f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
676f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
677b4f971dfSStefano Zampini   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
678f26d0771SStefano Zampini   PetscFunctionReturn(0);
679f26d0771SStefano Zampini }
680f26d0771SStefano Zampini 
681f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
682a8116848SStefano Zampini {
683a8116848SStefano Zampini   PetscInt      *owners = map->range;
684a8116848SStefano Zampini   PetscInt       n      = map->n;
685a8116848SStefano Zampini   PetscSF        sf;
686a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
687a8116848SStefano Zampini   PetscSFNode   *ridxs;
688a8116848SStefano Zampini   PetscMPIInt    rank;
689a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
690a8116848SStefano Zampini   PetscErrorCode ierr;
691a8116848SStefano Zampini 
692a8116848SStefano Zampini   PetscFunctionBegin;
693fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
694a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
695a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
696a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
697a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
698a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
699a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
700a8116848SStefano Zampini     const PetscInt idx = idxs[r];
701a8116848SStefano 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);
702a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
703a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
704a8116848SStefano Zampini     }
705a8116848SStefano Zampini     ridxs[r].rank = p;
706a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
707a8116848SStefano Zampini   }
708a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
709a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
710a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
711a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
712f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
713a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
714f0ae7da4SStefano Zampini 
715f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
716a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
717a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
718a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
719a8116848SStefano Zampini     start -= cum;
720a8116848SStefano Zampini     cum = 0;
721a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
722a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
723a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
724a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
725a8116848SStefano Zampini   }
726a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
727a8116848SStefano Zampini   /* Compress and put in indices */
728a8116848SStefano Zampini   for (r = 0; r < n; ++r)
729a8116848SStefano Zampini     if (lidxs[r] >= 0) {
730a8116848SStefano Zampini       if (work) work[len] = work[r];
731a8116848SStefano Zampini       lidxs[len++] = r;
732a8116848SStefano Zampini     }
733a8116848SStefano Zampini   if (on) *on = len;
734a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
735a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
736a8116848SStefano Zampini   PetscFunctionReturn(0);
737a8116848SStefano Zampini }
738a8116848SStefano Zampini 
7397dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
740a8116848SStefano Zampini {
741a8116848SStefano Zampini   Mat               locmat,newlocmat;
742a8116848SStefano Zampini   Mat_IS            *newmatis;
743a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
744a8116848SStefano Zampini   Vec               rtest,ltest;
745a8116848SStefano Zampini   const PetscScalar *array;
746a8116848SStefano Zampini #endif
747a8116848SStefano Zampini   const PetscInt    *idxs;
748a8116848SStefano Zampini   PetscInt          i,m,n;
749a8116848SStefano Zampini   PetscErrorCode    ierr;
750a8116848SStefano Zampini 
751a8116848SStefano Zampini   PetscFunctionBegin;
752a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
753a8116848SStefano Zampini     PetscBool ismatis;
754a8116848SStefano Zampini 
755a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
756a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
757a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
758a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
759a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
760a8116848SStefano Zampini   }
761a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
762a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
763a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
764a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
765a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
766a8116848SStefano Zampini   for (i=0;i<n;i++) {
767a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
768a8116848SStefano Zampini   }
769a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
770a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
771a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
772a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
773a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
774fd479f66SMatthew 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]));
775a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
776a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
777a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
778a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
779a8116848SStefano Zampini   for (i=0;i<n;i++) {
780a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
781a8116848SStefano Zampini   }
782a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
783a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
784a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
785a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
786a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
787fd479f66SMatthew 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]));
788a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
789a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
790a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
791a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
792a8116848SStefano Zampini #endif
793a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
794a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
795a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
796a8116848SStefano Zampini     IS                     is;
797a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
798306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
799a8116848SStefano Zampini     MPI_Comm               comm;
800a8116848SStefano Zampini 
801a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
802306cf5c7SStefano Zampini     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
803306cf5c7SStefano Zampini     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
804306cf5c7SStefano Zampini     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
805306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
806306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
807a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
808a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
809a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
810a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
811a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
812306cf5c7SStefano Zampini     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
813a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
814a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
815f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
816a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
8173d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
8183d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
819a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
820a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
821a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
822a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
823a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
8243d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
825a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
826a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8273d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
828a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
829a8116848SStefano Zampini         lidxs[newloc] = i;
830a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
831a8116848SStefano Zampini       }
832a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
833a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
834306cf5c7SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
835a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
836a8116848SStefano Zampini     /* local is to extract local submatrix */
837a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
838a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
839a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
840a8116848SStefano Zampini       PetscBool cong;
84126b0207aSStefano Zampini 
842a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
843a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
844a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
845a8116848SStefano Zampini     }
846268753edSStefano Zampini     if (mat->congruentlayouts && irow == icol && matis->csf == matis->sf) {
847a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
848a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
849a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
850a8116848SStefano Zampini     } else {
851a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
852a8116848SStefano Zampini 
853a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
854a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
855f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
856a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
8573d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
858a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
859a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
860a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
861a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
862a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
8633d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
864a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
865a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8663d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
867a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
868a8116848SStefano Zampini           lidxs[newloc] = i;
869a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
870a8116848SStefano Zampini         }
871a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
872a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
873306cf5c7SStefano Zampini       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
874a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
875a8116848SStefano Zampini       /* local is to extract local submatrix */
876a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
877a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
878a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
879a8116848SStefano Zampini     }
880a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
881a8116848SStefano Zampini   } else {
882a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
883a8116848SStefano Zampini   }
884a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
885a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
8867dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
887a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
888a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
889a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
890a8116848SStefano Zampini   }
891a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
892a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
893a8116848SStefano Zampini   PetscFunctionReturn(0);
894a8116848SStefano Zampini }
895a8116848SStefano Zampini 
896a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
8972b404112SStefano Zampini {
8982b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
8992b404112SStefano Zampini   PetscBool      ismatis;
9002b404112SStefano Zampini   PetscErrorCode ierr;
9012b404112SStefano Zampini 
9022b404112SStefano Zampini   PetscFunctionBegin;
9032b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
9042b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
9052b404112SStefano Zampini   b = (Mat_IS*)B->data;
9062b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
907cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
9082b404112SStefano Zampini   PetscFunctionReturn(0);
9092b404112SStefano Zampini }
9102b404112SStefano Zampini 
911a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
9126bd84002SStefano Zampini {
913527b2640SStefano Zampini   Vec               v;
914527b2640SStefano Zampini   const PetscScalar *array;
915527b2640SStefano Zampini   PetscInt          i,n;
9166bd84002SStefano Zampini   PetscErrorCode    ierr;
9176bd84002SStefano Zampini 
9186bd84002SStefano Zampini   PetscFunctionBegin;
919527b2640SStefano Zampini   *missing = PETSC_FALSE;
920527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
921527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
922527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
923527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
924527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
925527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
926527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
927527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
928527b2640SStefano Zampini   if (d) {
929527b2640SStefano Zampini     *d = -1;
930527b2640SStefano Zampini     if (*missing) {
931527b2640SStefano Zampini       PetscInt rstart;
932527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
933527b2640SStefano Zampini       *d = i+rstart;
934527b2640SStefano Zampini     }
935527b2640SStefano Zampini   }
9366bd84002SStefano Zampini   PetscFunctionReturn(0);
9376bd84002SStefano Zampini }
9386bd84002SStefano Zampini 
939cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
94028f4e0baSStefano Zampini {
94128f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
94228f4e0baSStefano Zampini   const PetscInt *gidxs;
9434f2d7cafSStefano Zampini   PetscInt       nleaves;
94428f4e0baSStefano Zampini   PetscErrorCode ierr;
94528f4e0baSStefano Zampini 
94628f4e0baSStefano Zampini   PetscFunctionBegin;
9474f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
94828f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
9493bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9504f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
9514f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
9523bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9534f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
954a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
9553d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
956a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
957a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9583d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
959a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9603d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
961a8116848SStefano Zampini   } else {
962a8116848SStefano Zampini     matis->csf = matis->sf;
963a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
964a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
965a8116848SStefano Zampini   }
96628f4e0baSStefano Zampini   PetscFunctionReturn(0);
96728f4e0baSStefano Zampini }
9682e1947a5SStefano Zampini 
969eb82efa4SStefano Zampini /*@
970a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
971a88811baSStefano Zampini 
972a88811baSStefano Zampini    Collective on MPI_Comm
973a88811baSStefano Zampini 
974a88811baSStefano Zampini    Input Parameters:
975a88811baSStefano Zampini +  B - the matrix
976a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
977a88811baSStefano Zampini            (same value is used for all local rows)
978a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
979a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
980a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
981a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
982a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
983a88811baSStefano Zampini            the diagonal entry even if it is zero.
984a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
985a88811baSStefano Zampini            submatrix (same value is used for all local rows).
986a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
987a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
988a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
989a88811baSStefano Zampini            structure. The size of this array is equal to the number
990a88811baSStefano Zampini            of local rows, i.e 'm'.
991a88811baSStefano Zampini 
992a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
993a88811baSStefano Zampini 
994a88811baSStefano Zampini    Level: intermediate
995a88811baSStefano Zampini 
99695452b02SPatrick Sanan    Notes:
99795452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
998a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
999a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1000a88811baSStefano Zampini 
1001a88811baSStefano Zampini .keywords: matrix
1002a88811baSStefano Zampini 
10033c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1004a88811baSStefano Zampini @*/
10052e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10062e1947a5SStefano Zampini {
10072e1947a5SStefano Zampini   PetscErrorCode ierr;
10082e1947a5SStefano Zampini 
10092e1947a5SStefano Zampini   PetscFunctionBegin;
10102e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
10112e1947a5SStefano Zampini   PetscValidType(B,1);
10122e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
10132e1947a5SStefano Zampini   PetscFunctionReturn(0);
10142e1947a5SStefano Zampini }
10152e1947a5SStefano Zampini 
10167230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10172e1947a5SStefano Zampini {
10182e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
101928f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
10202e1947a5SStefano Zampini   PetscErrorCode ierr;
10212e1947a5SStefano Zampini 
10222e1947a5SStefano Zampini   PetscFunctionBegin;
10236c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1024cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
10254f2d7cafSStefano Zampini 
10264f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
10274f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
10284f2d7cafSStefano Zampini 
10294f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
10304f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
10314f2d7cafSStefano Zampini 
103228f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
103328f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
103428f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
103528f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
10364f2d7cafSStefano Zampini 
10374f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
103828f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
10390f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
10400f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
10410f2f62c7SStefano Zampini #endif
10424f2d7cafSStefano Zampini 
10434f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
104428f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10454f2d7cafSStefano Zampini 
10464f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
104728f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10480f2f62c7SStefano Zampini 
10490f2f62c7SStefano Zampini   /* for other matrix types */
10500f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
10512e1947a5SStefano Zampini   PetscFunctionReturn(0);
10522e1947a5SStefano Zampini }
1053b4319ba4SBarry Smith 
10543927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
10553927de2eSStefano Zampini {
10563927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
10573927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1058ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
10593927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
10603927de2eSStefano Zampini   PetscInt        lrows,lcols;
10613927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
10623927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
10633927de2eSStefano Zampini   PetscBool       isdense,issbaij;
10643927de2eSStefano Zampini   PetscErrorCode  ierr;
10653927de2eSStefano Zampini 
10663927de2eSStefano Zampini   PetscFunctionBegin;
10673927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
10683927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
10693927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
10703927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
10713927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
10723927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1073ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1074ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
10757230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1076ecf5a873SStefano Zampini   } else {
1077ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1078ecf5a873SStefano Zampini   }
1079ecf5a873SStefano Zampini 
10803927de2eSStefano Zampini   if (issbaij) {
10813927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
10823927de2eSStefano Zampini   }
10833927de2eSStefano Zampini   /*
1084ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
10853927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
10863927de2eSStefano Zampini   */
1087cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
10883927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
10893927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
10903927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
10913927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
10923927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
10933927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
10943927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
10953927de2eSStefano Zampini       row_ownership[j] = i;
10963927de2eSStefano Zampini     }
10973927de2eSStefano Zampini   }
10987230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
10993927de2eSStefano Zampini 
11003927de2eSStefano Zampini   /*
11013927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
11023927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
11033927de2eSStefano Zampini   */
11043927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
11053927de2eSStefano Zampini   /* preallocation as a MATAIJ */
11063927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
11073927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
110812dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
110912dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1110ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
11113927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11123927de2eSStefano Zampini           my_dnz[i] += 1;
11133927de2eSStefano Zampini         } else { /* offdiag block */
11143927de2eSStefano Zampini           my_onz[i] += 1;
11153927de2eSStefano Zampini         }
11163927de2eSStefano Zampini       }
11173927de2eSStefano Zampini     }
1118bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1119bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1120bb1015c3SStefano Zampini     PetscBool      done;
1121bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1122938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1123bb1015c3SStefano Zampini     jptr = jj;
1124bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1125bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1126bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1127bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1128bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1129bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1130bb1015c3SStefano Zampini           my_dnz[i] += 1;
1131bb1015c3SStefano Zampini         } else { /* offdiag block */
1132bb1015c3SStefano Zampini           my_onz[i] += 1;
1133bb1015c3SStefano Zampini         }
1134bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1135bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1136bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1137bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1138bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1139bb1015c3SStefano Zampini           } else {
1140bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1141bb1015c3SStefano Zampini           }
1142bb1015c3SStefano Zampini         }
1143bb1015c3SStefano Zampini       }
1144bb1015c3SStefano Zampini     }
1145bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1146938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1147bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
11483927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
11493927de2eSStefano Zampini       const PetscInt *cols;
1150ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
11513927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11523927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
11533927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1154ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
11553927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11563927de2eSStefano Zampini           my_dnz[i] += 1;
11573927de2eSStefano Zampini         } else { /* offdiag block */
11583927de2eSStefano Zampini           my_onz[i] += 1;
11593927de2eSStefano Zampini         }
11603927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1161d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
11623927de2eSStefano Zampini           owner = row_ownership[index_col];
11633927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1164d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
11653927de2eSStefano Zampini           } else {
1166d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
11673927de2eSStefano Zampini           }
11683927de2eSStefano Zampini         }
11693927de2eSStefano Zampini       }
11703927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11713927de2eSStefano Zampini     }
11723927de2eSStefano Zampini   }
1173ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
11747230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1175ecf5a873SStefano Zampini   }
11764f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
11773927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1178ecf5a873SStefano Zampini 
1179ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
11803927de2eSStefano Zampini   if (maxreduce) {
11813927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11823927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1183bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11843927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
11853927de2eSStefano Zampini   } else {
11863927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
11873927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1188bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
11893927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
11903927de2eSStefano Zampini   }
11913927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
11923927de2eSStefano Zampini 
11933927de2eSStefano Zampini   /* Resize preallocation if overestimated */
11943927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
11953927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
11963927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
11973927de2eSStefano Zampini   }
11981670daf9Sstefano_zampini 
11991670daf9Sstefano_zampini   /* Set preallocation */
1200268753edSStefano Zampini   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
12013927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
12023927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
12033927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
12043927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
12053927de2eSStefano Zampini   }
1206268753edSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
12073927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12083927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12093927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
12103927de2eSStefano Zampini   if (issbaij) {
12113927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
12123927de2eSStefano Zampini   }
12133927de2eSStefano Zampini   PetscFunctionReturn(0);
12143927de2eSStefano Zampini }
12153927de2eSStefano Zampini 
12167230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1217b7ce53b6SStefano Zampini {
1218b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1219d9a9e74cSStefano Zampini   Mat            local_mat;
1220b7ce53b6SStefano Zampini   /* info on mat */
12213cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1222b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1223b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1224b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1225b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1226b9ed4604SStefano Zampini #endif
12277c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1228b7ce53b6SStefano Zampini   /* values insertion */
1229b7ce53b6SStefano Zampini   PetscScalar    *array;
1230b7ce53b6SStefano Zampini   /* work */
1231b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1232b7ce53b6SStefano Zampini 
1233b7ce53b6SStefano Zampini   PetscFunctionBegin;
1234b7ce53b6SStefano Zampini   /* get info from mat */
12357c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
12367c03b4e8SStefano Zampini   if (nsubdomains == 1) {
12371670daf9Sstefano_zampini     Mat            B;
12381670daf9Sstefano_zampini     IS             rows,cols;
1239acdf38a7Sstefano_zampini     IS             irows,icols;
12401670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
12411670daf9Sstefano_zampini 
12421670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
12431670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
12441670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
12451670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
1246acdf38a7Sstefano_zampini     ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1247acdf38a7Sstefano_zampini     ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1248acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr);
1249acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr);
1250268753edSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
1251268753edSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1252acdf38a7Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
1253acdf38a7Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
12546104e0f1Sstefano_zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
12557dae84e0SHong Zhang     ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1256acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1257acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1258acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
12597c03b4e8SStefano Zampini     PetscFunctionReturn(0);
12607c03b4e8SStefano Zampini   }
1261b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1262b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
12633cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1264b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1265b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
12664099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1267b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1268b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1269b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1270b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1271b9ed4604SStefano Zampini   lb[0] = isseqdense;
1272b9ed4604SStefano Zampini   lb[1] = isseqaij;
1273b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1274b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1275b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1276b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1277b9ed4604SStefano Zampini #endif
1278b7ce53b6SStefano Zampini 
1279b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
12803927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
12813cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
1282b9ed4604SStefano Zampini     if (!isseqsbaij) {
1283b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1284b9ed4604SStefano Zampini     } else {
1285b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1286b9ed4604SStefano Zampini     }
1287d59cf9ebSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
12883927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1289b7ce53b6SStefano Zampini   } else {
12903cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1291b7ce53b6SStefano Zampini     /* some checks */
1292b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1293b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
12943cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
12956c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
12966c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
12976c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
12986c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
12996c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1300b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1301b7ce53b6SStefano Zampini   }
1302d9a9e74cSStefano Zampini 
1303b9ed4604SStefano Zampini   if (isseqsbaij) {
1304d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1305d9a9e74cSStefano Zampini   } else {
1306d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1307d9a9e74cSStefano Zampini     local_mat = matis->A;
1308d9a9e74cSStefano Zampini   }
1309686e3a49SStefano Zampini 
1310b7ce53b6SStefano Zampini   /* Set values */
1311ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1312b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
131365066ba5SStefano Zampini     PetscInt i,*dummy;
1314ecf5a873SStefano Zampini 
131565066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
131665066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
1317b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1318d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
131965066ba5SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
1320d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
132165066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
1322686e3a49SStefano Zampini   } else if (isseqaij) {
1323ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1324686e3a49SStefano Zampini     PetscBool done;
1325686e3a49SStefano Zampini 
1326d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1327938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1328d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1329686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1330ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1331686e3a49SStefano Zampini     }
1332d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1333938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1334d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1335686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1336ecf5a873SStefano Zampini     PetscInt i;
1337c0962df8SStefano Zampini 
1338686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1339686e3a49SStefano Zampini       PetscInt       j;
1340ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1341686e3a49SStefano Zampini 
1342ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1343ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1344ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1345686e3a49SStefano Zampini     }
1346b7ce53b6SStefano Zampini   }
1347b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1348d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1349b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1350b9ed4604SStefano Zampini   if (isseqdense) {
1351b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1352b7ce53b6SStefano Zampini   }
1353b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1354b7ce53b6SStefano Zampini }
1355b7ce53b6SStefano Zampini 
1356b7ce53b6SStefano Zampini /*@
1357b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1358b7ce53b6SStefano Zampini 
1359b7ce53b6SStefano Zampini   Input Parameter:
1360b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1361b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1362b7ce53b6SStefano Zampini 
1363b7ce53b6SStefano Zampini   Output Parameter:
1364b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1365b7ce53b6SStefano Zampini 
1366b7ce53b6SStefano Zampini   Level: developer
1367b7ce53b6SStefano Zampini 
136895452b02SPatrick Sanan   Notes:
136995452b02SPatrick Sanan     mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1370b7ce53b6SStefano Zampini 
1371b7ce53b6SStefano Zampini .seealso: MATIS
1372b7ce53b6SStefano Zampini @*/
1373b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1374b7ce53b6SStefano Zampini {
1375b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1376b7ce53b6SStefano Zampini 
1377b7ce53b6SStefano Zampini   PetscFunctionBegin;
1378b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1379b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1380b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1381b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1382b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1383b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
13846c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1385b7ce53b6SStefano Zampini   }
1386b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1387b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1388b7ce53b6SStefano Zampini }
1389b7ce53b6SStefano Zampini 
1390ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1391ad6194a2SStefano Zampini {
1392ad6194a2SStefano Zampini   PetscErrorCode ierr;
1393ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1394ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1395ad6194a2SStefano Zampini   Mat            B,localmat;
1396ad6194a2SStefano Zampini 
1397ad6194a2SStefano Zampini   PetscFunctionBegin;
1398ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1399ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1400ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1401e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1402ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1403ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1404b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1405ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1406ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1407ad6194a2SStefano Zampini   *newmat = B;
1408ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1409ad6194a2SStefano Zampini }
1410ad6194a2SStefano Zampini 
1411a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
141269796d55SStefano Zampini {
141369796d55SStefano Zampini   PetscErrorCode ierr;
141469796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
141569796d55SStefano Zampini   PetscBool      local_sym;
141669796d55SStefano Zampini 
141769796d55SStefano Zampini   PetscFunctionBegin;
141869796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1419b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
142069796d55SStefano Zampini   PetscFunctionReturn(0);
142169796d55SStefano Zampini }
142269796d55SStefano Zampini 
1423a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
142469796d55SStefano Zampini {
142569796d55SStefano Zampini   PetscErrorCode ierr;
142669796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
142769796d55SStefano Zampini   PetscBool      local_sym;
142869796d55SStefano Zampini 
142969796d55SStefano Zampini   PetscFunctionBegin;
143069796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1431b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
143269796d55SStefano Zampini   PetscFunctionReturn(0);
143369796d55SStefano Zampini }
143469796d55SStefano Zampini 
143545471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
143645471136SStefano Zampini {
143745471136SStefano Zampini   PetscErrorCode ierr;
143845471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
143945471136SStefano Zampini   PetscBool      local_sym;
144045471136SStefano Zampini 
144145471136SStefano Zampini   PetscFunctionBegin;
144245471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
144345471136SStefano Zampini     *flg = PETSC_FALSE;
144445471136SStefano Zampini     PetscFunctionReturn(0);
144545471136SStefano Zampini   }
144645471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
144745471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
144845471136SStefano Zampini   PetscFunctionReturn(0);
144945471136SStefano Zampini }
145045471136SStefano Zampini 
1451a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1452b4319ba4SBarry Smith {
1453dfbe8321SBarry Smith   PetscErrorCode ierr;
1454b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1455b4319ba4SBarry Smith 
1456b4319ba4SBarry Smith   PetscFunctionBegin;
14576bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1458e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1459e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
14606bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
14616bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
14623fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1463a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1464a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1465a8116848SStefano Zampini   if (b->sf != b->csf) {
1466a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1467a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1468a8116848SStefano Zampini   }
146928f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
147028f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1471bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1472dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1473bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1474b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1475b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
14762e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1477cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1478b4319ba4SBarry Smith   PetscFunctionReturn(0);
1479b4319ba4SBarry Smith }
1480b4319ba4SBarry Smith 
1481a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1482b4319ba4SBarry Smith {
1483dfbe8321SBarry Smith   PetscErrorCode ierr;
1484b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1485b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1486b4319ba4SBarry Smith 
1487b4319ba4SBarry Smith   PetscFunctionBegin;
1488b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1489e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1490e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1491b4319ba4SBarry Smith 
1492b4319ba4SBarry Smith   /* multiply the local matrix */
1493b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1494b4319ba4SBarry Smith 
1495b4319ba4SBarry Smith   /* scatter product back into global memory */
14962dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1497e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1498e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1499b4319ba4SBarry Smith   PetscFunctionReturn(0);
1500b4319ba4SBarry Smith }
1501b4319ba4SBarry Smith 
1502a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15032e74eeadSLisandro Dalcin {
1504650997f4SStefano Zampini   Vec            temp_vec;
15052e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15062e74eeadSLisandro Dalcin 
15072e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1508650997f4SStefano Zampini   if (v3 != v2) {
1509650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1510650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1511650997f4SStefano Zampini   } else {
1512650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1513650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1514650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1515650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1516650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1517650997f4SStefano Zampini   }
15182e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15192e74eeadSLisandro Dalcin }
15202e74eeadSLisandro Dalcin 
1521a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
15222e74eeadSLisandro Dalcin {
15232e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
15242e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15252e74eeadSLisandro Dalcin 
1526e176bc59SStefano Zampini   PetscFunctionBegin;
15272e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1528e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1529e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15302e74eeadSLisandro Dalcin 
15312e74eeadSLisandro Dalcin   /* multiply the local matrix */
1532e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
15332e74eeadSLisandro Dalcin 
15342e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1535e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1536e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1537e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15382e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15392e74eeadSLisandro Dalcin }
15402e74eeadSLisandro Dalcin 
1541a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15422e74eeadSLisandro Dalcin {
1543650997f4SStefano Zampini   Vec            temp_vec;
15442e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15452e74eeadSLisandro Dalcin 
15462e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1547650997f4SStefano Zampini   if (v3 != v2) {
1548650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1549650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1550650997f4SStefano Zampini   } else {
1551650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1552650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1553650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1554650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1555650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1556650997f4SStefano Zampini   }
15572e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15582e74eeadSLisandro Dalcin }
15592e74eeadSLisandro Dalcin 
1560a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1561b4319ba4SBarry Smith {
1562b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1563dfbe8321SBarry Smith   PetscErrorCode ierr;
1564b4319ba4SBarry Smith   PetscViewer    sviewer;
1565ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1566b4319ba4SBarry Smith 
1567b4319ba4SBarry Smith   PetscFunctionBegin;
1568ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1569ee2491ecSStefano Zampini   if (isascii)  {
1570ee2491ecSStefano Zampini     PetscViewerFormat format;
1571ee2491ecSStefano Zampini 
1572ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1573ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1574ee2491ecSStefano Zampini   }
1575ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
15763f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1577b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
15783f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
15796e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1580b4319ba4SBarry Smith   PetscFunctionReturn(0);
1581b4319ba4SBarry Smith }
1582b4319ba4SBarry Smith 
1583a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1584b4319ba4SBarry Smith {
1585dfbe8321SBarry Smith   PetscErrorCode ierr;
1586e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1587b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1588b4319ba4SBarry Smith   IS             from,to;
1589e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1590b4319ba4SBarry Smith 
1591b4319ba4SBarry Smith   PetscFunctionBegin;
1592784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1593e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
15943bbff08aSStefano Zampini   /* Destroy any previous data */
159570cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
159670cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
15973fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1598e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1599e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
16001c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
1601872cf891SStefano Zampini   if (is->csf != is->sf) {
1602872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
1603872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
1604872cf891SStefano Zampini   }
160528f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
160628f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
16073bbff08aSStefano Zampini 
16083bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1609fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1610fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1611e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1612e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1613e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1614e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
16156625354bSStefano Zampini   /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */
16166625354bSStefano Zampini   if (rmapping != cmapping && A->rmap->N == A->cmap->N) {
16176625354bSStefano Zampini     PetscBool same,gsame;
16186625354bSStefano Zampini 
16196625354bSStefano Zampini     same = PETSC_FALSE;
16206625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
16216625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
16226625354bSStefano Zampini 
16236625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
16246625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
16256625354bSStefano Zampini       ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr);
16266625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
16276625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
16286625354bSStefano Zampini     }
16296625354bSStefano Zampini     ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
16306625354bSStefano Zampini     if (gsame) cmapping = rmapping;
16316625354bSStefano Zampini   }
16326625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
16336625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
16346625354bSStefano Zampini 
16356625354bSStefano Zampini   /* Create the local matrix A */
1636f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1637e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1638e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1639e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1640ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1641ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1642b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1643c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
1644c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
1645b4319ba4SBarry Smith 
1646f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1647b4319ba4SBarry Smith     /* Create the local work vectors */
16483bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1649b4319ba4SBarry Smith 
1650e176bc59SStefano Zampini     /* setup the global to local scatters */
1651e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1652e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1653784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1654e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1655e176bc59SStefano Zampini     if (rmapping != cmapping) {
1656e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1657e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1658e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1659e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1660e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1661e176bc59SStefano Zampini     } else {
1662e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1663e176bc59SStefano Zampini       is->cctx = is->rctx;
1664e176bc59SStefano Zampini     }
16653fd1c9e7SStefano Zampini 
16663fd1c9e7SStefano Zampini     /* interface counter vector (local) */
16673fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
16683fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
16693fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16703fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16713fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16723fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16733fd1c9e7SStefano Zampini 
16743fd1c9e7SStefano Zampini     /* free workspace */
1675e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1676e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
16776bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
16786bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1679f26d0771SStefano Zampini   }
168048ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1681b4319ba4SBarry Smith   PetscFunctionReturn(0);
1682b4319ba4SBarry Smith }
1683b4319ba4SBarry Smith 
1684a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
16852e74eeadSLisandro Dalcin {
16862e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
16872e74eeadSLisandro Dalcin   PetscErrorCode ierr;
168897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
168997563a80SStefano Zampini   PetscInt       i,zm,zn;
169097563a80SStefano Zampini #endif
1691f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
16922e74eeadSLisandro Dalcin 
16932e74eeadSLisandro Dalcin   PetscFunctionBegin;
16942e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1695f26d0771SStefano 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);
169697563a80SStefano Zampini   /* count negative indices */
169797563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
169897563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
16992e74eeadSLisandro Dalcin #endif
170097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
170197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
170297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
170397563a80SStefano Zampini   /* count negative indices (should be the same as before) */
170497563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
170597563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
1706b4f971dfSStefano 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");
1707b4f971dfSStefano 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");
170897563a80SStefano Zampini #endif
17092e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
17102e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
17112e74eeadSLisandro Dalcin }
17122e74eeadSLisandro Dalcin 
1713a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
171497563a80SStefano Zampini {
171597563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
171697563a80SStefano Zampini   PetscErrorCode ierr;
171797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
171897563a80SStefano Zampini   PetscInt       i,zm,zn;
171997563a80SStefano Zampini #endif
1720f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
172197563a80SStefano Zampini 
172297563a80SStefano Zampini   PetscFunctionBegin;
172397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1724f26d0771SStefano 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);
172597563a80SStefano Zampini   /* count negative indices */
172697563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
172797563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
172897563a80SStefano Zampini #endif
172997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
173097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
173197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
173297563a80SStefano Zampini   /* count negative indices (should be the same as before) */
173397563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
173497563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
1735b4f971dfSStefano 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");
1736b4f971dfSStefano 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");
173797563a80SStefano Zampini #endif
1738d59cf9ebSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
173997563a80SStefano Zampini   PetscFunctionReturn(0);
174097563a80SStefano Zampini }
174197563a80SStefano Zampini 
1742a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1743b4319ba4SBarry Smith {
1744dfbe8321SBarry Smith   PetscErrorCode ierr;
1745b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1746b4319ba4SBarry Smith 
1747b4319ba4SBarry Smith   PetscFunctionBegin;
1748b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
1749872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1750872cf891SStefano Zampini   } else {
1751b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1752872cf891SStefano Zampini   }
1753b4319ba4SBarry Smith   PetscFunctionReturn(0);
1754b4319ba4SBarry Smith }
1755b4319ba4SBarry Smith 
1756a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1757f0006bf2SLisandro Dalcin {
1758f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1759f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1760f0006bf2SLisandro Dalcin 
1761f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1762b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
1763b4f971dfSStefano Zampini #if defined(PETSC_USE_DEBUG)
1764b4f971dfSStefano Zampini     PetscInt ibs,bs;
1765b4f971dfSStefano Zampini 
1766b4f971dfSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
1767b4f971dfSStefano Zampini     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
1768b4f971dfSStefano Zampini     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
1769b4f971dfSStefano Zampini #endif
1770b4f971dfSStefano Zampini     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1771b4f971dfSStefano Zampini   } else {
1772f0006bf2SLisandro Dalcin     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1773b4f971dfSStefano Zampini   }
1774f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1775f0006bf2SLisandro Dalcin }
1776f0006bf2SLisandro Dalcin 
1777f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1778f0ae7da4SStefano Zampini {
1779f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1780f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1781f0ae7da4SStefano Zampini 
1782f0ae7da4SStefano Zampini   PetscFunctionBegin;
1783f0ae7da4SStefano Zampini   if (!n) {
1784f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1785f0ae7da4SStefano Zampini   } else {
1786f0ae7da4SStefano Zampini     PetscInt i;
1787f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1788f0ae7da4SStefano Zampini 
1789f0ae7da4SStefano Zampini     if (columns) {
1790f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1791f0ae7da4SStefano Zampini     } else {
1792f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1793f0ae7da4SStefano Zampini     }
1794f0ae7da4SStefano Zampini     if (diag != 0.) {
1795f0ae7da4SStefano Zampini       const PetscScalar *array;
1796f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1797f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1798f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1799f0ae7da4SStefano Zampini       }
1800f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1801f0ae7da4SStefano Zampini     }
1802f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1803f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1804f0ae7da4SStefano Zampini   }
1805f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1806f0ae7da4SStefano Zampini }
1807f0ae7da4SStefano Zampini 
1808f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
18092e74eeadSLisandro Dalcin {
18106e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
18116e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
18126e520ac8SStefano Zampini   PetscInt       *lrows;
18132e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18142e74eeadSLisandro Dalcin 
18152e74eeadSLisandro Dalcin   PetscFunctionBegin;
1816f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1817f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1818f0ae7da4SStefano Zampini     PetscBool cong;
181926b0207aSStefano Zampini 
1820f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
182126b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
1822268753edSStefano 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");
1823268753edSStefano 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");
1824268753edSStefano 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");
1825f0ae7da4SStefano Zampini   }
1826f0ae7da4SStefano Zampini #endif
18276e520ac8SStefano Zampini   /* get locally owned rows */
1828f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
18296e520ac8SStefano Zampini   /* fix right hand side if needed */
18306e520ac8SStefano Zampini   if (x && b) {
18316e520ac8SStefano Zampini     const PetscScalar *xx;
18326e520ac8SStefano Zampini     PetscScalar       *bb;
18336e520ac8SStefano Zampini 
18346e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
18356e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
18366e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
18376e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
18386e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
18392e74eeadSLisandro Dalcin   }
18406e520ac8SStefano Zampini   /* get rows associated to the local matrices */
18413d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
18426e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
18436e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
18446e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
18456e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
18466e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18476e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18486e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18496e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
18506e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1851f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
18526e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18532e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18542e74eeadSLisandro Dalcin }
18552e74eeadSLisandro Dalcin 
1856f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1857b4319ba4SBarry Smith {
1858dfbe8321SBarry Smith   PetscErrorCode ierr;
1859b4319ba4SBarry Smith 
1860b4319ba4SBarry Smith   PetscFunctionBegin;
1861f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1862f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1863f0ae7da4SStefano Zampini }
18642205254eSKarl Rupp 
1865f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1866f0ae7da4SStefano Zampini {
1867f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1868f0ae7da4SStefano Zampini 
1869f0ae7da4SStefano Zampini   PetscFunctionBegin;
1870f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1871b4319ba4SBarry Smith   PetscFunctionReturn(0);
1872b4319ba4SBarry Smith }
1873b4319ba4SBarry Smith 
1874a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1875b4319ba4SBarry Smith {
1876b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1877dfbe8321SBarry Smith   PetscErrorCode ierr;
1878b4319ba4SBarry Smith 
1879b4319ba4SBarry Smith   PetscFunctionBegin;
1880b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1881b4319ba4SBarry Smith   PetscFunctionReturn(0);
1882b4319ba4SBarry Smith }
1883b4319ba4SBarry Smith 
1884a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1885b4319ba4SBarry Smith {
1886b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1887dfbe8321SBarry Smith   PetscErrorCode ierr;
1888b4319ba4SBarry Smith 
1889b4319ba4SBarry Smith   PetscFunctionBegin;
1890b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1891872cf891SStefano Zampini   /* fix for local empty rows/cols */
1892872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
1893872cf891SStefano Zampini     Mat                    newlA;
1894872cf891SStefano Zampini     ISLocalToGlobalMapping l2g;
1895872cf891SStefano Zampini     IS                     tis;
1896872cf891SStefano Zampini     const PetscScalar      *v;
1897872cf891SStefano Zampini     PetscInt               i,n,cf,*loce,*locf;
1898872cf891SStefano Zampini     PetscBool              sym;
1899872cf891SStefano Zampini 
1900872cf891SStefano Zampini     ierr = MatGetRowMaxAbs(is->A,is->y,NULL);CHKERRQ(ierr);
1901872cf891SStefano Zampini     ierr = MatIsSymmetric(is->A,PETSC_SMALL,&sym);CHKERRQ(ierr);
1902872cf891SStefano Zampini     if (!sym) SETERRQ(PetscObjectComm((PetscObject)is->A),PETSC_ERR_SUP,"Not yet implemented for unsymmetric case");
1903872cf891SStefano Zampini     ierr = VecGetLocalSize(is->y,&n);CHKERRQ(ierr);
1904872cf891SStefano Zampini     ierr = PetscMalloc1(n,&loce);CHKERRQ(ierr);
1905872cf891SStefano Zampini     ierr = PetscMalloc1(n,&locf);CHKERRQ(ierr);
1906872cf891SStefano Zampini     ierr = VecGetArrayRead(is->y,&v);CHKERRQ(ierr);
1907872cf891SStefano Zampini     for (i=0,cf=0;i<n;i++) {
1908872cf891SStefano Zampini       if (v[i] == 0.0) {
1909872cf891SStefano Zampini         loce[i] = -1;
1910872cf891SStefano Zampini       } else {
1911872cf891SStefano Zampini         loce[i]    = cf;
1912872cf891SStefano Zampini         locf[cf++] = i;
1913872cf891SStefano Zampini       }
1914872cf891SStefano Zampini     }
1915872cf891SStefano Zampini     ierr = VecRestoreArrayRead(is->y,&v);CHKERRQ(ierr);
1916872cf891SStefano Zampini     /* extract valid submatrix */
1917872cf891SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A),cf,locf,PETSC_USE_POINTER,&tis);CHKERRQ(ierr);
1918e5b89577SStefano Zampini     ierr = MatCreateSubMatrix(is->A,tis,tis,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
1919872cf891SStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
1920872cf891SStefano Zampini     /* attach local l2g map for successive calls of MatSetValues */
1921872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is->A),1,n,loce,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
1922872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(newlA,l2g,l2g);CHKERRQ(ierr);
1923872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
1924872cf891SStefano Zampini     /* attach new global l2g map */
1925872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,cf,locf,locf);CHKERRQ(ierr);
1926872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,cf,locf,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
1927872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(A,l2g,l2g);CHKERRQ(ierr);
1928872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
1929872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
1930872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
1931872cf891SStefano Zampini   }
1932872cf891SStefano Zampini   is->locempty = PETSC_FALSE;
1933b4319ba4SBarry Smith   PetscFunctionReturn(0);
1934b4319ba4SBarry Smith }
1935b4319ba4SBarry Smith 
1936a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1937b4319ba4SBarry Smith {
1938b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1939b4319ba4SBarry Smith 
1940b4319ba4SBarry Smith   PetscFunctionBegin;
1941b4319ba4SBarry Smith   *local = is->A;
1942b4319ba4SBarry Smith   PetscFunctionReturn(0);
1943b4319ba4SBarry Smith }
1944b4319ba4SBarry Smith 
19453b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
19463b3b1effSJed Brown {
19473b3b1effSJed Brown   PetscFunctionBegin;
19483b3b1effSJed Brown   *local = NULL;
19493b3b1effSJed Brown   PetscFunctionReturn(0);
19503b3b1effSJed Brown }
19513b3b1effSJed Brown 
1952b4319ba4SBarry Smith /*@
1953b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1954b4319ba4SBarry Smith 
1955b4319ba4SBarry Smith   Input Parameter:
1956b4319ba4SBarry Smith .  mat - the matrix
1957b4319ba4SBarry Smith 
1958b4319ba4SBarry Smith   Output Parameter:
1959eb82efa4SStefano Zampini .  local - the local matrix
1960b4319ba4SBarry Smith 
1961b4319ba4SBarry Smith   Level: advanced
1962b4319ba4SBarry Smith 
1963b4319ba4SBarry Smith   Notes:
1964b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1965b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1966b4319ba4SBarry Smith   of the MatSetValues() operation.
1967b4319ba4SBarry Smith 
19683b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
196996a6f129SJed Brown 
1970b4319ba4SBarry Smith .seealso: MATIS
1971b4319ba4SBarry Smith @*/
19727087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1973b4319ba4SBarry Smith {
19744ac538c5SBarry Smith   PetscErrorCode ierr;
1975b4319ba4SBarry Smith 
1976b4319ba4SBarry Smith   PetscFunctionBegin;
19770700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1978b4319ba4SBarry Smith   PetscValidPointer(local,2);
19794ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1980b4319ba4SBarry Smith   PetscFunctionReturn(0);
1981b4319ba4SBarry Smith }
1982b4319ba4SBarry Smith 
19833b3b1effSJed Brown /*@
19843b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
19853b3b1effSJed Brown 
19863b3b1effSJed Brown   Input Parameter:
19873b3b1effSJed Brown .  mat - the matrix
19883b3b1effSJed Brown 
19893b3b1effSJed Brown   Output Parameter:
19903b3b1effSJed Brown .  local - the local matrix
19913b3b1effSJed Brown 
19923b3b1effSJed Brown   Level: advanced
19933b3b1effSJed Brown 
19943b3b1effSJed Brown .seealso: MATIS
19953b3b1effSJed Brown @*/
19963b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
19973b3b1effSJed Brown {
19983b3b1effSJed Brown   PetscErrorCode ierr;
19993b3b1effSJed Brown 
20003b3b1effSJed Brown   PetscFunctionBegin;
20013b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
20023b3b1effSJed Brown   PetscValidPointer(local,2);
20033b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
20043b3b1effSJed Brown   PetscFunctionReturn(0);
20053b3b1effSJed Brown }
20063b3b1effSJed Brown 
2007a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
20083b03a366Sstefano_zampini {
20093b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
20103b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
20113b03a366Sstefano_zampini   PetscErrorCode ierr;
20123b03a366Sstefano_zampini 
20133b03a366Sstefano_zampini   PetscFunctionBegin;
20144e4c7dbeSStefano Zampini   if (is->A) {
20153b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
20163b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2017f0ae7da4SStefano 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);
20184e4c7dbeSStefano Zampini   }
20193b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
20203b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
20213b03a366Sstefano_zampini   is->A = local;
20223b03a366Sstefano_zampini   PetscFunctionReturn(0);
20233b03a366Sstefano_zampini }
20243b03a366Sstefano_zampini 
20253b03a366Sstefano_zampini /*@
2026eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
20273b03a366Sstefano_zampini 
20283b03a366Sstefano_zampini   Input Parameter:
20293b03a366Sstefano_zampini .  mat - the matrix
2030eb82efa4SStefano Zampini .  local - the local matrix
20313b03a366Sstefano_zampini 
20323b03a366Sstefano_zampini   Output Parameter:
20333b03a366Sstefano_zampini 
20343b03a366Sstefano_zampini   Level: advanced
20353b03a366Sstefano_zampini 
20363b03a366Sstefano_zampini   Notes:
20373b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
20383b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
20393b03a366Sstefano_zampini 
20403b03a366Sstefano_zampini .seealso: MATIS
20413b03a366Sstefano_zampini @*/
20423b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
20433b03a366Sstefano_zampini {
20443b03a366Sstefano_zampini   PetscErrorCode ierr;
20453b03a366Sstefano_zampini 
20463b03a366Sstefano_zampini   PetscFunctionBegin;
20473b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2048b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
20493b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
20503b03a366Sstefano_zampini   PetscFunctionReturn(0);
20513b03a366Sstefano_zampini }
20523b03a366Sstefano_zampini 
2053a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
20546726f965SBarry Smith {
20556726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
20566726f965SBarry Smith   PetscErrorCode ierr;
20576726f965SBarry Smith 
20586726f965SBarry Smith   PetscFunctionBegin;
20596726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
20606726f965SBarry Smith   PetscFunctionReturn(0);
20616726f965SBarry Smith }
20626726f965SBarry Smith 
2063a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
20642e74eeadSLisandro Dalcin {
20652e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20662e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20672e74eeadSLisandro Dalcin 
20682e74eeadSLisandro Dalcin   PetscFunctionBegin;
20692e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
20702e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20712e74eeadSLisandro Dalcin }
20722e74eeadSLisandro Dalcin 
2073a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
20742e74eeadSLisandro Dalcin {
20752e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20762e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20772e74eeadSLisandro Dalcin 
20782e74eeadSLisandro Dalcin   PetscFunctionBegin;
20792e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
2080e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
20812e74eeadSLisandro Dalcin 
20822e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
20832e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
2084e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2085e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20862e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20872e74eeadSLisandro Dalcin }
20882e74eeadSLisandro Dalcin 
2089a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
20906726f965SBarry Smith {
20916726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
20926726f965SBarry Smith   PetscErrorCode ierr;
20936726f965SBarry Smith 
20946726f965SBarry Smith   PetscFunctionBegin;
20954e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
20966726f965SBarry Smith   PetscFunctionReturn(0);
20976726f965SBarry Smith }
20986726f965SBarry Smith 
2099f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
2100f26d0771SStefano Zampini {
2101f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
2102f26d0771SStefano Zampini   Mat_IS         *x;
2103f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2104f26d0771SStefano Zampini   PetscBool      ismatis;
2105f26d0771SStefano Zampini #endif
2106f26d0771SStefano Zampini   PetscErrorCode ierr;
2107f26d0771SStefano Zampini 
2108f26d0771SStefano Zampini   PetscFunctionBegin;
2109f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2110f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
2111f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
2112f26d0771SStefano Zampini #endif
2113f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
2114f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
2115f26d0771SStefano Zampini   PetscFunctionReturn(0);
2116f26d0771SStefano Zampini }
2117f26d0771SStefano Zampini 
2118f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
2119f26d0771SStefano Zampini {
2120f26d0771SStefano Zampini   Mat                    lA;
2121f26d0771SStefano Zampini   Mat_IS                 *matis;
2122f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2123f26d0771SStefano Zampini   IS                     is;
2124f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
2125f26d0771SStefano Zampini   PetscInt               nrg;
2126f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
2127f26d0771SStefano Zampini   PetscErrorCode         ierr;
2128f26d0771SStefano Zampini 
2129f26d0771SStefano Zampini   PetscFunctionBegin;
2130f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2131f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
2132f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
2133f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
2134f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2135f0ae7da4SStefano 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);
2136f26d0771SStefano Zampini #endif
2137f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
2138f26d0771SStefano Zampini   /* map from [0,nrl) to row */
2139f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
2140f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2141f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
2142f26d0771SStefano Zampini #else
2143f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
2144f26d0771SStefano Zampini #endif
2145f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
2146f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2147f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2148f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2149f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
2150f26d0771SStefano Zampini   /* compute new l2g map for columns */
2151f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2152f26d0771SStefano Zampini     const PetscInt *cg,*cl;
2153f26d0771SStefano Zampini     PetscInt       ncg;
2154f26d0771SStefano Zampini     PetscInt       ncl;
2155f26d0771SStefano Zampini 
2156f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2157f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2158f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2159f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2160f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2161f0ae7da4SStefano 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);
2162f26d0771SStefano Zampini #endif
2163f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2164f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2165f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2166f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2167f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2168f26d0771SStefano Zampini #else
2169f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2170f26d0771SStefano Zampini #endif
2171f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2172f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2173f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2174f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2175f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2176f26d0771SStefano Zampini   } else {
2177f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2178f26d0771SStefano Zampini     cl2g = rl2g;
2179f26d0771SStefano Zampini   }
2180f26d0771SStefano Zampini   /* create the MATIS submatrix */
2181f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2182f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2183f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2184f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2185b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2186f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2187f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2188f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2189f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2190f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2191f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2192f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2193f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2194f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2195f26d0771SStefano Zampini   /* remove unsupported ops */
2196f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2197f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2198f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2199f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2200f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2201f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2202f26d0771SStefano Zampini   PetscFunctionReturn(0);
2203f26d0771SStefano Zampini }
2204f26d0771SStefano Zampini 
2205872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
2206872cf891SStefano Zampini {
2207872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
2208872cf891SStefano Zampini   PetscErrorCode ierr;
2209872cf891SStefano Zampini 
2210872cf891SStefano Zampini   PetscFunctionBegin;
2211872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
2212872cf891SStefano Zampini   ierr = PetscObjectOptionsBegin((PetscObject)A);
2213872cf891SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns",NULL,a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
2214872cf891SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
2215872cf891SStefano Zampini   PetscFunctionReturn(0);
2216872cf891SStefano Zampini }
2217872cf891SStefano Zampini 
2218284134d9SBarry Smith /*@
22193c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2220284134d9SBarry Smith        process but not across processes.
2221284134d9SBarry Smith 
2222284134d9SBarry Smith    Input Parameters:
2223284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2224e176bc59SStefano Zampini .     bs      - block size of the matrix
2225df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2226e176bc59SStefano Zampini .     rmap    - local to global map for rows
2227e176bc59SStefano Zampini -     cmap    - local to global map for cols
2228284134d9SBarry Smith 
2229284134d9SBarry Smith    Output Parameter:
2230284134d9SBarry Smith .    A - the resulting matrix
2231284134d9SBarry Smith 
22328e6c10adSSatish Balay    Level: advanced
22338e6c10adSSatish Balay 
223495452b02SPatrick Sanan    Notes:
223595452b02SPatrick Sanan     See MATIS for more details.
22366fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
22376fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
22383c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2239284134d9SBarry Smith 
2240284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2241284134d9SBarry Smith @*/
2242e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2243284134d9SBarry Smith {
2244284134d9SBarry Smith   PetscErrorCode ierr;
2245284134d9SBarry Smith 
2246284134d9SBarry Smith   PetscFunctionBegin;
22476fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2248284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2249284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
22506fdf41d1SStefano Zampini   if (bs > 0) {
2251284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
22526fdf41d1SStefano Zampini   }
2253284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2254e176bc59SStefano Zampini   if (rmap && cmap) {
2255e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2256e176bc59SStefano Zampini   } else if (!rmap) {
2257e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2258e176bc59SStefano Zampini   } else {
2259e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2260e176bc59SStefano Zampini   }
2261284134d9SBarry Smith   PetscFunctionReturn(0);
2262284134d9SBarry Smith }
2263284134d9SBarry Smith 
2264b4319ba4SBarry Smith /*MC
2265f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2266b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2267b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2268b4319ba4SBarry Smith    product is handled "implicitly".
2269b4319ba4SBarry Smith 
2270b4319ba4SBarry Smith    Operations Provided:
22716726f965SBarry Smith +  MatMult()
22722e74eeadSLisandro Dalcin .  MatMultAdd()
22732e74eeadSLisandro Dalcin .  MatMultTranspose()
22742e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
22756726f965SBarry Smith .  MatZeroEntries()
22766726f965SBarry Smith .  MatSetOption()
22772e74eeadSLisandro Dalcin .  MatZeroRows()
22782e74eeadSLisandro Dalcin .  MatSetValues()
227997563a80SStefano Zampini .  MatSetValuesBlocked()
22806726f965SBarry Smith .  MatSetValuesLocal()
228197563a80SStefano Zampini .  MatSetValuesBlockedLocal()
22822e74eeadSLisandro Dalcin .  MatScale()
22832e74eeadSLisandro Dalcin .  MatGetDiagonal()
22842b404112SStefano Zampini .  MatMissingDiagonal()
22852b404112SStefano Zampini .  MatDuplicate()
22862b404112SStefano Zampini .  MatCopy()
2287f26d0771SStefano Zampini .  MatAXPY()
22887dae84e0SHong Zhang .  MatCreateSubMatrix()
2289f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2290d7f69cd0SStefano Zampini .  MatTranspose()
22916726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2292b4319ba4SBarry Smith 
2293b4319ba4SBarry Smith    Options Database Keys:
2294b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2295b4319ba4SBarry Smith 
229695452b02SPatrick Sanan    Notes:
229795452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
2298b4319ba4SBarry Smith 
2299b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2300b4319ba4SBarry Smith 
2301b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2302eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2303b4319ba4SBarry Smith 
2304b4319ba4SBarry Smith   Level: advanced
2305b4319ba4SBarry Smith 
2306f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2307b4319ba4SBarry Smith 
2308b4319ba4SBarry Smith M*/
2309b4319ba4SBarry Smith 
23108cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2311b4319ba4SBarry Smith {
2312dfbe8321SBarry Smith   PetscErrorCode ierr;
2313b4319ba4SBarry Smith   Mat_IS         *b;
2314b4319ba4SBarry Smith 
2315b4319ba4SBarry Smith   PetscFunctionBegin;
2316b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2317b4319ba4SBarry Smith   A->data = (void*)b;
2318b4319ba4SBarry Smith 
2319e176bc59SStefano Zampini   /* matrix ops */
2320e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2321b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
23222e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
23232e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
23242e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2325b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2326b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
23272e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
232898921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2329b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2330f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
23312e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2332f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2333b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2334b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2335b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
23366726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
23372e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
23382e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
23396726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
234069796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
234169796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
234245471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2343ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
23446bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
23452b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2346659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
23477dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
2348f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
23493fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
23503fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2351d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
23527fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
2353ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
2354872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
2355b4319ba4SBarry Smith 
2356b7ce53b6SStefano Zampini   /* special MATIS functions */
2357bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
23583b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
2359bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2360b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
23612e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2362cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
236317667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2364b4319ba4SBarry Smith   PetscFunctionReturn(0);
2365b4319ba4SBarry Smith }
2366