xref: /petsc/src/mat/impls/is/matis.c (revision b0f2910eac86e2230a6ad8b3f3d5b63e8df584e0)
1b4319ba4SBarry Smith /*
2b4319ba4SBarry Smith     Creates a matrix class for using the Neumann-Neumann type preconditioners.
3b4319ba4SBarry Smith     This stores the matrices in globally unassembled form. Each processor
4b4319ba4SBarry Smith     assembles only its local Neumann problem and the parallel matrix vector
5b4319ba4SBarry Smith     product is handled "implicitly".
6b4319ba4SBarry Smith 
7b4319ba4SBarry Smith     Currently this allows for only one subdomain per processor.
8b4319ba4SBarry Smith */
9b4319ba4SBarry Smith 
10c6db04a5SJed Brown #include <../src/mat/impls/is/matis.h>      /*I "petscmat.h" I*/
116989cf23SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
124f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h>
1328f4e0baSStefano Zampini 
14f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
15b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
16b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
17f26d0771SStefano Zampini 
185b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
195b003df0Sstefano_zampini {
205b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
215b003df0Sstefano_zampini   PetscInt         i;
225b003df0Sstefano_zampini   PetscErrorCode   ierr;
235b003df0Sstefano_zampini 
24ab4d48faSStefano Zampini   PetscFunctionBegin;
255b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
265b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
275b003df0Sstefano_zampini   }
285b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
295b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
305b003df0Sstefano_zampini   }
315b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
325b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
335b003df0Sstefano_zampini   PetscFunctionReturn(0);
345b003df0Sstefano_zampini }
35a72627d2SStefano Zampini 
365b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyArray_Private(void *ptr)
377fa8f2d3SStefano Zampini {
386989cf23SStefano Zampini   PetscErrorCode ierr;
396989cf23SStefano Zampini 
406989cf23SStefano Zampini   PetscFunctionBeginUser;
416989cf23SStefano Zampini   ierr = PetscFree(ptr);CHKERRQ(ierr);
426989cf23SStefano Zampini   PetscFunctionReturn(0);
436989cf23SStefano Zampini }
446989cf23SStefano Zampini 
456989cf23SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
466989cf23SStefano Zampini {
476989cf23SStefano Zampini   Mat_MPIAIJ             *aij  = (Mat_MPIAIJ*)A->data;
486989cf23SStefano Zampini   Mat_SeqAIJ             *diag = (Mat_SeqAIJ*)(aij->A->data);
496989cf23SStefano Zampini   Mat_SeqAIJ             *offd = (Mat_SeqAIJ*)(aij->B->data);
506989cf23SStefano Zampini   Mat                    lA;
516989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
526989cf23SStefano Zampini   IS                     is;
536989cf23SStefano Zampini   MPI_Comm               comm;
546989cf23SStefano Zampini   void                   *ptrs[2];
556989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
566989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
576989cf23SStefano Zampini   PetscInt               *di,*dj,*oi,*oj;
586989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
59e363d98aSStefano Zampini   PetscInt               lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
606989cf23SStefano Zampini   PetscErrorCode         ierr;
616989cf23SStefano Zampini 
62ab4d48faSStefano Zampini   PetscFunctionBegin;
636989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
646989cf23SStefano Zampini   if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present");
656989cf23SStefano Zampini 
666989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
676989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
686989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
696989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
706989cf23SStefano Zampini   di   = diag->i;
716989cf23SStefano Zampini   dj   = diag->j;
726989cf23SStefano Zampini   dd   = diag->a;
736989cf23SStefano Zampini   oc   = aij->B->cmap->n;
746989cf23SStefano Zampini   oi   = offd->i;
756989cf23SStefano Zampini   oj   = offd->j;
766989cf23SStefano Zampini   od   = offd->a;
776989cf23SStefano Zampini   nnz  = diag->i[dr] + offd->i[dr];
786989cf23SStefano Zampini 
796989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
806989cf23SStefano Zampini   ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
816989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
826989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
83e363d98aSStefano Zampini   if (dr) {
846989cf23SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
856989cf23SStefano Zampini     for (i=0; i<dc; i++) aux[i]    = i+stc;
866989cf23SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i];
876989cf23SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
88e363d98aSStefano Zampini     lc   = dc+oc;
89e363d98aSStefano Zampini   } else {
90e363d98aSStefano Zampini     ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
91e363d98aSStefano Zampini     lc   = 0;
92e363d98aSStefano Zampini   }
936989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
946989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
956989cf23SStefano Zampini 
966989cf23SStefano Zampini   /* create MATIS object */
976989cf23SStefano Zampini   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
986989cf23SStefano Zampini   ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
996989cf23SStefano Zampini   ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1006989cf23SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1016989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1026989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1036989cf23SStefano Zampini 
1046989cf23SStefano Zampini   /* merge local matrices */
1056989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
1066989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
1076989cf23SStefano Zampini   ii   = aux;
1086989cf23SStefano Zampini   jj   = aux+dr+1;
1096989cf23SStefano Zampini   aa   = data;
1106989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
1116989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
1126989cf23SStefano Zampini   {
1136989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
1146989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
1156989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
1166989cf23SStefano Zampini   }
1176989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
1186989cf23SStefano Zampini   ii   = aux;
1196989cf23SStefano Zampini   jj   = aux+dr+1;
1206989cf23SStefano Zampini   aa   = data;
121e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
1226989cf23SStefano Zampini 
1236989cf23SStefano Zampini   /* create containers to destroy the data */
1246989cf23SStefano Zampini   ptrs[0] = aux;
1256989cf23SStefano Zampini   ptrs[1] = data;
1266989cf23SStefano Zampini   for (i=0; i<2; i++) {
1276989cf23SStefano Zampini     PetscContainer c;
1286989cf23SStefano Zampini 
1296989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
1306989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
1315b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyArray_Private);CHKERRQ(ierr);
1326989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
1336989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
1346989cf23SStefano Zampini   }
1356989cf23SStefano Zampini 
1366989cf23SStefano Zampini   /* finalize matrix */
1376989cf23SStefano Zampini   ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
1386989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
1396989cf23SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1406989cf23SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1416989cf23SStefano Zampini   PetscFunctionReturn(0);
1426989cf23SStefano Zampini }
1436989cf23SStefano Zampini 
144cf0a3239SStefano Zampini /*@
1453d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
146cf0a3239SStefano Zampini 
147cf0a3239SStefano Zampini    Collective on MPI_Comm
148cf0a3239SStefano Zampini 
149cf0a3239SStefano Zampini    Input Parameters:
150cf0a3239SStefano Zampini +  A - the matrix
151cf0a3239SStefano Zampini 
152cf0a3239SStefano Zampini    Level: advanced
153cf0a3239SStefano Zampini 
1543d996552SStefano Zampini    Notes: This function does not need to be called by the user.
155cf0a3239SStefano Zampini 
156cf0a3239SStefano Zampini .keywords: matrix
157cf0a3239SStefano Zampini 
158cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
159cf0a3239SStefano Zampini @*/
160cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
161cf0a3239SStefano Zampini {
1627fa8f2d3SStefano Zampini   PetscErrorCode ierr;
1637fa8f2d3SStefano Zampini 
1647fa8f2d3SStefano Zampini   PetscFunctionBegin;
165cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
166cf0a3239SStefano Zampini   PetscValidType(A,1);
167cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
1687fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
1697fa8f2d3SStefano Zampini }
1707fa8f2d3SStefano Zampini 
1715e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1725e3038f0Sstefano_zampini {
1735e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
1745e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
1755e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
1765e3038f0Sstefano_zampini   MPI_Comm               comm;
1775b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
1785b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
1799e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
1805e3038f0Sstefano_zampini   PetscErrorCode         ierr;
1815e3038f0Sstefano_zampini 
182ab4d48faSStefano Zampini   PetscFunctionBegin;
1835e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
1845e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
1855e3038f0Sstefano_zampini   rnest  = NULL;
1865e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
1875e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
1885e3038f0Sstefano_zampini 
1895e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1905e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
1915e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
1925e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
1935e3038f0Sstefano_zampini     if (isnest) {
1945e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
1955e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
1965e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
1975e3038f0Sstefano_zampini     }
1985e3038f0Sstefano_zampini   }
1995e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
2005b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
2019e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
2025e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
2039e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
2045e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
2055e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2065e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2075e3038f0Sstefano_zampini       PetscBool ismatis;
2089e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
2095e3038f0Sstefano_zampini 
2105e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
2115e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2125e3038f0Sstefano_zampini 
2135e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
2149e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
2159e7b2b25Sstefano_zampini       if (istrans[ij]) {
2169e7b2b25Sstefano_zampini         Mat T,lT;
2179e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2189e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
2199e7b2b25Sstefano_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);
2209e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
2219e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
2229e7b2b25Sstefano_zampini       } else {
2235e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
2245e3038f0Sstefano_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);
2259e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
2269e7b2b25Sstefano_zampini       }
2275e3038f0Sstefano_zampini 
2285e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
2295e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
2309e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
2315e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
2325e3038f0Sstefano_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);
2335e3038f0Sstefano_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);
2345e3038f0Sstefano_zampini       lr[i] = l1;
2355e3038f0Sstefano_zampini       lc[j] = l2;
2365e3038f0Sstefano_zampini 
2375e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
2385e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
2395e3038f0Sstefano_zampini     }
2405e3038f0Sstefano_zampini   }
2415e3038f0Sstefano_zampini 
2425e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
2435e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
2445e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2455e3038f0Sstefano_zampini     rl2g = NULL;
2465e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2475e3038f0Sstefano_zampini       PetscInt n1,n2;
2485e3038f0Sstefano_zampini 
2495e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2509e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
2519e7b2b25Sstefano_zampini         Mat T;
2529e7b2b25Sstefano_zampini 
2539e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2549e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
2559e7b2b25Sstefano_zampini       } else {
2565e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
2579e7b2b25Sstefano_zampini       }
2585e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2595e3038f0Sstefano_zampini       if (!n1) continue;
2605e3038f0Sstefano_zampini       if (!rl2g) {
2615e3038f0Sstefano_zampini         rl2g = cl2g;
2625e3038f0Sstefano_zampini       } else {
2635e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2645e3038f0Sstefano_zampini         PetscBool      same;
2655e3038f0Sstefano_zampini 
2665e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2675e3038f0Sstefano_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);
2685e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2695e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2705e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2715e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2725e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2735e3038f0Sstefano_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);
2745e3038f0Sstefano_zampini       }
2755e3038f0Sstefano_zampini     }
2765e3038f0Sstefano_zampini   }
2775e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
2785e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
2795e3038f0Sstefano_zampini     rl2g = NULL;
2805e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
2815e3038f0Sstefano_zampini       PetscInt n1,n2;
2825e3038f0Sstefano_zampini 
2835e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
2849e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
2859e7b2b25Sstefano_zampini         Mat T;
2869e7b2b25Sstefano_zampini 
2879e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
2889e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
2899e7b2b25Sstefano_zampini       } else {
2905e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
2919e7b2b25Sstefano_zampini       }
2925e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2935e3038f0Sstefano_zampini       if (!n1) continue;
2945e3038f0Sstefano_zampini       if (!rl2g) {
2955e3038f0Sstefano_zampini         rl2g = cl2g;
2965e3038f0Sstefano_zampini       } else {
2975e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2985e3038f0Sstefano_zampini         PetscBool      same;
2995e3038f0Sstefano_zampini 
3005e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
3015e3038f0Sstefano_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);
3025e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
3035e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
3045e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
3055e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
3065e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
3075e3038f0Sstefano_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);
3085e3038f0Sstefano_zampini       }
3095e3038f0Sstefano_zampini     }
3105e3038f0Sstefano_zampini   }
3115e3038f0Sstefano_zampini #endif
3125e3038f0Sstefano_zampini 
3135e3038f0Sstefano_zampini   B = NULL;
3145e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
3155b003df0Sstefano_zampini     PetscInt stl;
3165b003df0Sstefano_zampini 
3175e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
3185e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
3195e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3205b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
3215e3038f0Sstefano_zampini       Mat            usedmat;
3225e3038f0Sstefano_zampini       Mat_IS         *matis;
3235e3038f0Sstefano_zampini       const PetscInt *idxs;
3245e3038f0Sstefano_zampini 
3255e3038f0Sstefano_zampini       /* local IS for local NEST */
3265b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
3275e3038f0Sstefano_zampini 
3285e3038f0Sstefano_zampini       /* l2gmap */
3295e3038f0Sstefano_zampini       j = 0;
3305e3038f0Sstefano_zampini       usedmat = nest[i][j];
3319e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
3329e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
3339e7b2b25Sstefano_zampini 
3349e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3359e7b2b25Sstefano_zampini         Mat T;
3369e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3379e7b2b25Sstefano_zampini         usedmat = T;
3389e7b2b25Sstefano_zampini       }
33982d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3405e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3415e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
3429e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3439e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3449e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3459e7b2b25Sstefano_zampini       } else {
3465e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3475e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3489e7b2b25Sstefano_zampini       }
3495e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
3505e3038f0Sstefano_zampini       stl += lr[i];
3515e3038f0Sstefano_zampini     }
3525e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
3535e3038f0Sstefano_zampini 
3545e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
3555e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
3565e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3575b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
3585e3038f0Sstefano_zampini       Mat            usedmat;
3595e3038f0Sstefano_zampini       Mat_IS         *matis;
3605e3038f0Sstefano_zampini       const PetscInt *idxs;
3615e3038f0Sstefano_zampini 
3625e3038f0Sstefano_zampini       /* local IS for local NEST */
3635b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
3645e3038f0Sstefano_zampini 
3655e3038f0Sstefano_zampini       /* l2gmap */
3665e3038f0Sstefano_zampini       j = 0;
3675e3038f0Sstefano_zampini       usedmat = nest[j][i];
3689e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
3699e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
3709e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3719e7b2b25Sstefano_zampini         Mat T;
3729e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3739e7b2b25Sstefano_zampini         usedmat = T;
3749e7b2b25Sstefano_zampini       }
37582d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3765e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3775e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
3789e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3799e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3809e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3819e7b2b25Sstefano_zampini       } else {
3825e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3835e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3849e7b2b25Sstefano_zampini       }
3855e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
3865e3038f0Sstefano_zampini       stl += lc[i];
3875e3038f0Sstefano_zampini     }
3885e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
3895e3038f0Sstefano_zampini 
3905e3038f0Sstefano_zampini     /* Create MATIS */
3915e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
3925e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
3935e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
3945e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
3955e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
3965e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
3975e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3985e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3995e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
4009e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
4019e7b2b25Sstefano_zampini       if (istrans[i]) {
4029e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
4039e7b2b25Sstefano_zampini       }
4049e7b2b25Sstefano_zampini     }
4055e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
4065e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
4075e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4085e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4095e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
4105e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
4115e3038f0Sstefano_zampini     } else {
4125e3038f0Sstefano_zampini       *newmat = B;
4135e3038f0Sstefano_zampini     }
4145e3038f0Sstefano_zampini   } else {
4155e3038f0Sstefano_zampini     if (lreuse) {
4165e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4175e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
4185e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
4195e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
4205e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
4219e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
4229e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
4239e7b2b25Sstefano_zampini             }
4245e3038f0Sstefano_zampini           }
4255e3038f0Sstefano_zampini         }
4265e3038f0Sstefano_zampini       }
4275e3038f0Sstefano_zampini     } else {
4285b003df0Sstefano_zampini       PetscInt stl;
4295b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
4305b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
4315b003df0Sstefano_zampini         stl  += lr[i];
4325e3038f0Sstefano_zampini       }
4335b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
4345b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
4355b003df0Sstefano_zampini         stl  += lc[i];
4365e3038f0Sstefano_zampini       }
4375e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
438ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
4399e7b2b25Sstefano_zampini         if (istrans[i]) {
4409e7b2b25Sstefano_zampini           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
4419e7b2b25Sstefano_zampini         }
442ab4d48faSStefano Zampini       }
4435e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
4445e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
4455e3038f0Sstefano_zampini     }
4465e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4475e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4485e3038f0Sstefano_zampini   }
4495e3038f0Sstefano_zampini 
4505b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
4515b003df0Sstefano_zampini   convert = PETSC_FALSE;
4525b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
4535b003df0Sstefano_zampini   if (convert) {
4545b003df0Sstefano_zampini     Mat              M;
4555b003df0Sstefano_zampini     MatISLocalFields lf;
4565b003df0Sstefano_zampini     PetscContainer   c;
4575b003df0Sstefano_zampini 
4585b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4595b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
4605b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
4615b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
4625b003df0Sstefano_zampini 
4635b003df0Sstefano_zampini     /* attach local fields to the matrix */
4645b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
4655b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
4665b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
4675b003df0Sstefano_zampini       PetscInt n,st;
4685b003df0Sstefano_zampini 
4695b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
4705b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
4715b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
4725b003df0Sstefano_zampini     }
4735b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
4745b003df0Sstefano_zampini       PetscInt n,st;
4755b003df0Sstefano_zampini 
4765b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
4775b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
4785b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
4795b003df0Sstefano_zampini     }
4805b003df0Sstefano_zampini     lf->nr = nr;
4815b003df0Sstefano_zampini     lf->nc = nc;
4825b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
4835b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
4845b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
4855b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
4865b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
4875b003df0Sstefano_zampini   }
4885b003df0Sstefano_zampini 
4895e3038f0Sstefano_zampini   /* Free workspace */
4905e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4915e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
4925e3038f0Sstefano_zampini   }
4935e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
4945e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
4955e3038f0Sstefano_zampini   }
4969e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
4975b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
4985e3038f0Sstefano_zampini   PetscFunctionReturn(0);
4995e3038f0Sstefano_zampini }
5005e3038f0Sstefano_zampini 
501ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
502ad219c80Sstefano_zampini {
503ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
504ad219c80Sstefano_zampini   Vec               ll,rr;
505ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
506ad219c80Sstefano_zampini   PetscScalar       *x,*y;
507ad219c80Sstefano_zampini   PetscErrorCode    ierr;
508ad219c80Sstefano_zampini 
509ad219c80Sstefano_zampini   PetscFunctionBegin;
510ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
511ad219c80Sstefano_zampini   if (l) {
512ad219c80Sstefano_zampini     ll   = matis->y;
513ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
514ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
515ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
516ad219c80Sstefano_zampini   } else {
517ad219c80Sstefano_zampini     ll = NULL;
518ad219c80Sstefano_zampini   }
519ad219c80Sstefano_zampini   if (r) {
520ad219c80Sstefano_zampini     rr   = matis->x;
521ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
522ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
523ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
524ad219c80Sstefano_zampini   } else {
525ad219c80Sstefano_zampini     rr = NULL;
526ad219c80Sstefano_zampini   }
527ad219c80Sstefano_zampini   if (ll) {
528ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
529ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
530ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
531ad219c80Sstefano_zampini   }
532ad219c80Sstefano_zampini   if (rr) {
533ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
534ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
535ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
536ad219c80Sstefano_zampini   }
537ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
538ad219c80Sstefano_zampini   PetscFunctionReturn(0);
539ad219c80Sstefano_zampini }
540ad219c80Sstefano_zampini 
5417fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
5427fa8f2d3SStefano Zampini {
5437fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
5447fa8f2d3SStefano Zampini   MatInfo        info;
5457fa8f2d3SStefano Zampini   PetscReal      isend[6],irecv[6];
5467fa8f2d3SStefano Zampini   PetscInt       bs;
5477fa8f2d3SStefano Zampini   PetscErrorCode ierr;
5487fa8f2d3SStefano Zampini 
5497fa8f2d3SStefano Zampini   PetscFunctionBegin;
5507fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
5517fa8f2d3SStefano Zampini   if (matis->A->ops->getinfo) {
5527fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
5537fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
5547fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
5557fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
5567fa8f2d3SStefano Zampini     isend[3] = info.memory;
5577fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
5587fa8f2d3SStefano Zampini   } else {
5597fa8f2d3SStefano Zampini     isend[0] = 0.;
5607fa8f2d3SStefano Zampini     isend[1] = 0.;
5617fa8f2d3SStefano Zampini     isend[2] = 0.;
5627fa8f2d3SStefano Zampini     isend[3] = 0.;
5637fa8f2d3SStefano Zampini     isend[4] = 0.;
5647fa8f2d3SStefano Zampini   }
5657fa8f2d3SStefano Zampini   isend[5] = matis->A->num_ass;
5667fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
5677fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
5687fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
5697fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
5707fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
5717fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
5727fa8f2d3SStefano Zampini     ginfo->assemblies   = isend[5];
5737fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
5747fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
5757fa8f2d3SStefano Zampini 
5767fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
5777fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
5787fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
5797fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
5807fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
5817fa8f2d3SStefano Zampini     ginfo->assemblies   = irecv[5];
5827fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
5837fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
5847fa8f2d3SStefano Zampini 
5857fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
5867fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
5877fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
5887fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
5897fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
5907fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
591d7f69cd0SStefano Zampini   }
592d7f69cd0SStefano Zampini   ginfo->block_size        = bs;
593d7f69cd0SStefano Zampini   ginfo->fill_ratio_given  = 0;
594d7f69cd0SStefano Zampini   ginfo->fill_ratio_needed = 0;
595d7f69cd0SStefano Zampini   ginfo->factor_mallocs    = 0;
5965e3038f0Sstefano_zampini   PetscFunctionReturn(0);
5975e3038f0Sstefano_zampini }
5985e3038f0Sstefano_zampini 
599d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
600d7f69cd0SStefano Zampini {
601d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
602d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
603d7f69cd0SStefano Zampini 
604d7f69cd0SStefano Zampini   PetscFunctionBegin;
605cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
606cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
607d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
608d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
609d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
610d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
611d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
612d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
613cf37664fSBarry Smith   } else {
614cf37664fSBarry Smith     C = *B;
615d7f69cd0SStefano Zampini   }
616d7f69cd0SStefano Zampini 
617d7f69cd0SStefano Zampini   /* perform local transposition */
618d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
619d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
620d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
621d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
622d7f69cd0SStefano Zampini 
623cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
624d7f69cd0SStefano Zampini     *B = C;
625d7f69cd0SStefano Zampini   } else {
626d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
627d7f69cd0SStefano Zampini   }
6287aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6297aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
630d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
631d7f69cd0SStefano Zampini }
632d7f69cd0SStefano Zampini 
6333fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
6343fd1c9e7SStefano Zampini {
6353fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
6363fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6373fd1c9e7SStefano Zampini 
6383fd1c9e7SStefano Zampini   PetscFunctionBegin;
6394b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
6403fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6413fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6423fd1c9e7SStefano Zampini   }
6433fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
6443fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
6453fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6463fd1c9e7SStefano Zampini }
6473fd1c9e7SStefano Zampini 
6483fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
6493fd1c9e7SStefano Zampini {
6504b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
6513fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6523fd1c9e7SStefano Zampini 
6533fd1c9e7SStefano Zampini   PetscFunctionBegin;
6544b89b9cdSStefano Zampini   ierr = VecSet(is->y,a);CHKERRQ(ierr);
6553fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
6563fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6573fd1c9e7SStefano Zampini }
6583fd1c9e7SStefano Zampini 
659f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
660f26d0771SStefano Zampini {
661f26d0771SStefano Zampini   PetscErrorCode ierr;
662f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
663f26d0771SStefano Zampini 
664f26d0771SStefano Zampini   PetscFunctionBegin;
665f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
666f26d0771SStefano 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);
667f26d0771SStefano Zampini #endif
668f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
669f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
670b4f971dfSStefano Zampini   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
671f26d0771SStefano Zampini   PetscFunctionReturn(0);
672f26d0771SStefano Zampini }
673f26d0771SStefano Zampini 
674f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
675f26d0771SStefano Zampini {
676f26d0771SStefano Zampini   PetscErrorCode ierr;
677f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
678f26d0771SStefano Zampini 
679f26d0771SStefano Zampini   PetscFunctionBegin;
680f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
681f26d0771SStefano 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);
682f26d0771SStefano Zampini #endif
683f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
684f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
685b4f971dfSStefano Zampini   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
686f26d0771SStefano Zampini   PetscFunctionReturn(0);
687f26d0771SStefano Zampini }
688f26d0771SStefano Zampini 
689f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
690a8116848SStefano Zampini {
691a8116848SStefano Zampini   PetscInt      *owners = map->range;
692a8116848SStefano Zampini   PetscInt       n      = map->n;
693a8116848SStefano Zampini   PetscSF        sf;
694a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
695a8116848SStefano Zampini   PetscSFNode   *ridxs;
696a8116848SStefano Zampini   PetscMPIInt    rank;
697a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
698a8116848SStefano Zampini   PetscErrorCode ierr;
699a8116848SStefano Zampini 
700a8116848SStefano Zampini   PetscFunctionBegin;
701fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
702a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
703a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
704a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
705a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
706a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
707a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
708a8116848SStefano Zampini     const PetscInt idx = idxs[r];
709a8116848SStefano 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);
710a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
711a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
712a8116848SStefano Zampini     }
713a8116848SStefano Zampini     ridxs[r].rank = p;
714a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
715a8116848SStefano Zampini   }
716a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
717a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
718a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
719a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
720f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
721a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
722f0ae7da4SStefano Zampini 
723f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
724a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
725a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
726a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
727a8116848SStefano Zampini     start -= cum;
728a8116848SStefano Zampini     cum = 0;
729a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
730a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
731a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
732a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
733a8116848SStefano Zampini   }
734a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
735a8116848SStefano Zampini   /* Compress and put in indices */
736a8116848SStefano Zampini   for (r = 0; r < n; ++r)
737a8116848SStefano Zampini     if (lidxs[r] >= 0) {
738a8116848SStefano Zampini       if (work) work[len] = work[r];
739a8116848SStefano Zampini       lidxs[len++] = r;
740a8116848SStefano Zampini     }
741a8116848SStefano Zampini   if (on) *on = len;
742a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
743a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
744a8116848SStefano Zampini   PetscFunctionReturn(0);
745a8116848SStefano Zampini }
746a8116848SStefano Zampini 
7477dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
748a8116848SStefano Zampini {
749a8116848SStefano Zampini   Mat               locmat,newlocmat;
750a8116848SStefano Zampini   Mat_IS            *newmatis;
751a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
752a8116848SStefano Zampini   Vec               rtest,ltest;
753a8116848SStefano Zampini   const PetscScalar *array;
754a8116848SStefano Zampini #endif
755a8116848SStefano Zampini   const PetscInt    *idxs;
756a8116848SStefano Zampini   PetscInt          i,m,n;
757a8116848SStefano Zampini   PetscErrorCode    ierr;
758a8116848SStefano Zampini 
759a8116848SStefano Zampini   PetscFunctionBegin;
760a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
761a8116848SStefano Zampini     PetscBool ismatis;
762a8116848SStefano Zampini 
763a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
764a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
765a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
766a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
767a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
768a8116848SStefano Zampini   }
769a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
770a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
771a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
772a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
773a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
774a8116848SStefano Zampini   for (i=0;i<n;i++) {
775a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
776a8116848SStefano Zampini   }
777a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
778a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
779a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
780a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
781a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
782fd479f66SMatthew 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]));
783a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
784a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
785a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
786a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
787a8116848SStefano Zampini   for (i=0;i<n;i++) {
788a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
789a8116848SStefano Zampini   }
790a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
791a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
792a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
793a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
794a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
795fd479f66SMatthew 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]));
796a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
797a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
798a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
799a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
800a8116848SStefano Zampini #endif
801a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
802a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
803a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
804a8116848SStefano Zampini     IS                     is;
805a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
806306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
807a8116848SStefano Zampini     MPI_Comm               comm;
808a8116848SStefano Zampini 
809a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
810306cf5c7SStefano Zampini     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
811306cf5c7SStefano Zampini     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
812306cf5c7SStefano Zampini     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
813306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
814306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
815a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
816a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
817a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
818a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
819a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
820306cf5c7SStefano Zampini     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
821a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
822a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
823f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
824a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
8253d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
8263d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
827a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
828a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
829a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
830a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
831a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
8323d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
833a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
834a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8353d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
836a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
837a8116848SStefano Zampini         lidxs[newloc] = i;
838a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
839a8116848SStefano Zampini       }
840a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
841a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
842306cf5c7SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
843a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
844a8116848SStefano Zampini     /* local is to extract local submatrix */
845a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
846a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
847a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
848a8116848SStefano Zampini       PetscBool cong;
84926b0207aSStefano Zampini 
850a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
851a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
852a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
853a8116848SStefano Zampini     }
854268753edSStefano Zampini     if (mat->congruentlayouts && irow == icol && matis->csf == matis->sf) {
855a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
856a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
857a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
858a8116848SStefano Zampini     } else {
859a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
860a8116848SStefano Zampini 
861a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
862a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
863f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
864a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
8653d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
866a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
867a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
868a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
869a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
870a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
8713d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
872a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
873a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8743d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
875a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
876a8116848SStefano Zampini           lidxs[newloc] = i;
877a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
878a8116848SStefano Zampini         }
879a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
880a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
881306cf5c7SStefano Zampini       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
882a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
883a8116848SStefano Zampini       /* local is to extract local submatrix */
884a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
885a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
886a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
887a8116848SStefano Zampini     }
888a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
889a8116848SStefano Zampini   } else {
890a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
891a8116848SStefano Zampini   }
892a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
893a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
8947dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
895a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
896a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
897a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
898a8116848SStefano Zampini   }
899a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
900a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
901a8116848SStefano Zampini   PetscFunctionReturn(0);
902a8116848SStefano Zampini }
903a8116848SStefano Zampini 
904a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
9052b404112SStefano Zampini {
9062b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
9072b404112SStefano Zampini   PetscBool      ismatis;
9082b404112SStefano Zampini   PetscErrorCode ierr;
9092b404112SStefano Zampini 
9102b404112SStefano Zampini   PetscFunctionBegin;
9112b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
9122b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
9132b404112SStefano Zampini   b = (Mat_IS*)B->data;
9142b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
915cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
9162b404112SStefano Zampini   PetscFunctionReturn(0);
9172b404112SStefano Zampini }
9182b404112SStefano Zampini 
919a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
9206bd84002SStefano Zampini {
921527b2640SStefano Zampini   Vec               v;
922527b2640SStefano Zampini   const PetscScalar *array;
923527b2640SStefano Zampini   PetscInt          i,n;
9246bd84002SStefano Zampini   PetscErrorCode    ierr;
9256bd84002SStefano Zampini 
9266bd84002SStefano Zampini   PetscFunctionBegin;
927527b2640SStefano Zampini   *missing = PETSC_FALSE;
928527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
929527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
930527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
931527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
932527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
933527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
934527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
935527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
936527b2640SStefano Zampini   if (d) {
937527b2640SStefano Zampini     *d = -1;
938527b2640SStefano Zampini     if (*missing) {
939527b2640SStefano Zampini       PetscInt rstart;
940527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
941527b2640SStefano Zampini       *d = i+rstart;
942527b2640SStefano Zampini     }
943527b2640SStefano Zampini   }
9446bd84002SStefano Zampini   PetscFunctionReturn(0);
9456bd84002SStefano Zampini }
9466bd84002SStefano Zampini 
947cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
94828f4e0baSStefano Zampini {
94928f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
95028f4e0baSStefano Zampini   const PetscInt *gidxs;
9514f2d7cafSStefano Zampini   PetscInt       nleaves;
95228f4e0baSStefano Zampini   PetscErrorCode ierr;
95328f4e0baSStefano Zampini 
95428f4e0baSStefano Zampini   PetscFunctionBegin;
9554f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
95628f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
9573bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9584f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
9594f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
9603bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9614f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
962a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
9633d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
964a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
965a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9663d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
967a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9683d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
969a8116848SStefano Zampini   } else {
970a8116848SStefano Zampini     matis->csf = matis->sf;
971a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
972a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
973a8116848SStefano Zampini   }
97428f4e0baSStefano Zampini   PetscFunctionReturn(0);
97528f4e0baSStefano Zampini }
9762e1947a5SStefano Zampini 
977eb82efa4SStefano Zampini /*@
978a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
979a88811baSStefano Zampini 
980a88811baSStefano Zampini    Collective on MPI_Comm
981a88811baSStefano Zampini 
982a88811baSStefano Zampini    Input Parameters:
983a88811baSStefano Zampini +  B - the matrix
984a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
985a88811baSStefano Zampini            (same value is used for all local rows)
986a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
987a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
988a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
989a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
990a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
991a88811baSStefano Zampini            the diagonal entry even if it is zero.
992a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
993a88811baSStefano Zampini            submatrix (same value is used for all local rows).
994a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
995a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
996a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
997a88811baSStefano Zampini            structure. The size of this array is equal to the number
998a88811baSStefano Zampini            of local rows, i.e 'm'.
999a88811baSStefano Zampini 
1000a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1001a88811baSStefano Zampini 
1002a88811baSStefano Zampini    Level: intermediate
1003a88811baSStefano Zampini 
1004a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1005a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1006a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1007a88811baSStefano Zampini 
1008a88811baSStefano Zampini .keywords: matrix
1009a88811baSStefano Zampini 
10103c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1011a88811baSStefano Zampini @*/
10122e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10132e1947a5SStefano Zampini {
10142e1947a5SStefano Zampini   PetscErrorCode ierr;
10152e1947a5SStefano Zampini 
10162e1947a5SStefano Zampini   PetscFunctionBegin;
10172e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
10182e1947a5SStefano Zampini   PetscValidType(B,1);
10192e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
10202e1947a5SStefano Zampini   PetscFunctionReturn(0);
10212e1947a5SStefano Zampini }
10222e1947a5SStefano Zampini 
10237230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10242e1947a5SStefano Zampini {
10252e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
102628f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
10272e1947a5SStefano Zampini   PetscErrorCode ierr;
10282e1947a5SStefano Zampini 
10292e1947a5SStefano Zampini   PetscFunctionBegin;
10306c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1031cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
10324f2d7cafSStefano Zampini 
10334f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
10344f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
10354f2d7cafSStefano Zampini 
10364f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
10374f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
10384f2d7cafSStefano Zampini 
103928f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
104028f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
104128f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
104228f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
10434f2d7cafSStefano Zampini 
10444f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
104528f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
10460f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
10470f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
10480f2f62c7SStefano Zampini #endif
10494f2d7cafSStefano Zampini 
10504f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
105128f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10524f2d7cafSStefano Zampini 
10534f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
105428f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10550f2f62c7SStefano Zampini 
10560f2f62c7SStefano Zampini   /* for other matrix types */
10570f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
10582e1947a5SStefano Zampini   PetscFunctionReturn(0);
10592e1947a5SStefano Zampini }
1060b4319ba4SBarry Smith 
10613927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
10623927de2eSStefano Zampini {
10633927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
10643927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1065ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
10663927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
10673927de2eSStefano Zampini   PetscInt        lrows,lcols;
10683927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
10693927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
10703927de2eSStefano Zampini   PetscBool       isdense,issbaij;
10713927de2eSStefano Zampini   PetscErrorCode  ierr;
10723927de2eSStefano Zampini 
10733927de2eSStefano Zampini   PetscFunctionBegin;
10743927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
10753927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
10763927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
10773927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
10783927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
10793927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1080ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1081ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
10827230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1083ecf5a873SStefano Zampini   } else {
1084ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1085ecf5a873SStefano Zampini   }
1086ecf5a873SStefano Zampini 
10873927de2eSStefano Zampini   if (issbaij) {
10883927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
10893927de2eSStefano Zampini   }
10903927de2eSStefano Zampini   /*
1091ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
10923927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
10933927de2eSStefano Zampini   */
1094cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
10953927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
10963927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
10973927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
10983927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
10993927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
11003927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
11013927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
11023927de2eSStefano Zampini       row_ownership[j] = i;
11033927de2eSStefano Zampini     }
11043927de2eSStefano Zampini   }
11057230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
11063927de2eSStefano Zampini 
11073927de2eSStefano Zampini   /*
11083927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
11093927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
11103927de2eSStefano Zampini   */
11113927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
11123927de2eSStefano Zampini   /* preallocation as a MATAIJ */
11133927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
11143927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
111512dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
111612dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1117ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
11183927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11193927de2eSStefano Zampini           my_dnz[i] += 1;
11203927de2eSStefano Zampini         } else { /* offdiag block */
11213927de2eSStefano Zampini           my_onz[i] += 1;
11223927de2eSStefano Zampini         }
11233927de2eSStefano Zampini       }
11243927de2eSStefano Zampini     }
1125bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1126bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1127bb1015c3SStefano Zampini     PetscBool      done;
1128bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1129938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1130bb1015c3SStefano Zampini     jptr = jj;
1131bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1132bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1133bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1134bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1135bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1136bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1137bb1015c3SStefano Zampini           my_dnz[i] += 1;
1138bb1015c3SStefano Zampini         } else { /* offdiag block */
1139bb1015c3SStefano Zampini           my_onz[i] += 1;
1140bb1015c3SStefano Zampini         }
1141bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1142bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1143bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1144bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1145bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1146bb1015c3SStefano Zampini           } else {
1147bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1148bb1015c3SStefano Zampini           }
1149bb1015c3SStefano Zampini         }
1150bb1015c3SStefano Zampini       }
1151bb1015c3SStefano Zampini     }
1152bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1153938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1154bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
11553927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
11563927de2eSStefano Zampini       const PetscInt *cols;
1157ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
11583927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11593927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
11603927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1161ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
11623927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11633927de2eSStefano Zampini           my_dnz[i] += 1;
11643927de2eSStefano Zampini         } else { /* offdiag block */
11653927de2eSStefano Zampini           my_onz[i] += 1;
11663927de2eSStefano Zampini         }
11673927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1168d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
11693927de2eSStefano Zampini           owner = row_ownership[index_col];
11703927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1171d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
11723927de2eSStefano Zampini           } else {
1173d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
11743927de2eSStefano Zampini           }
11753927de2eSStefano Zampini         }
11763927de2eSStefano Zampini       }
11773927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11783927de2eSStefano Zampini     }
11793927de2eSStefano Zampini   }
1180ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
11817230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1182ecf5a873SStefano Zampini   }
11834f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
11843927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1185ecf5a873SStefano Zampini 
1186ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
11873927de2eSStefano Zampini   if (maxreduce) {
11883927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11893927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1190bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11913927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
11923927de2eSStefano Zampini   } else {
11933927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
11943927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1195bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
11963927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
11973927de2eSStefano Zampini   }
11983927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
11993927de2eSStefano Zampini 
12003927de2eSStefano Zampini   /* Resize preallocation if overestimated */
12013927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
12023927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
12033927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
12043927de2eSStefano Zampini   }
12051670daf9Sstefano_zampini 
12061670daf9Sstefano_zampini   /* Set preallocation */
1207268753edSStefano Zampini   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
12083927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
12093927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
12103927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
12113927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
12123927de2eSStefano Zampini   }
1213268753edSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
12143927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12153927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12163927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
12173927de2eSStefano Zampini   if (issbaij) {
12183927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
12193927de2eSStefano Zampini   }
12203927de2eSStefano Zampini   PetscFunctionReturn(0);
12213927de2eSStefano Zampini }
12223927de2eSStefano Zampini 
12237230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1224b7ce53b6SStefano Zampini {
1225b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1226d9a9e74cSStefano Zampini   Mat            local_mat;
1227b7ce53b6SStefano Zampini   /* info on mat */
12283cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1229b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1230b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1231b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1232b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1233b9ed4604SStefano Zampini #endif
12347c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1235b7ce53b6SStefano Zampini   /* values insertion */
1236b7ce53b6SStefano Zampini   PetscScalar    *array;
1237b7ce53b6SStefano Zampini   /* work */
1238b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1239b7ce53b6SStefano Zampini 
1240b7ce53b6SStefano Zampini   PetscFunctionBegin;
1241b7ce53b6SStefano Zampini   /* get info from mat */
12427c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
12437c03b4e8SStefano Zampini   if (nsubdomains == 1) {
12441670daf9Sstefano_zampini     Mat            B;
12451670daf9Sstefano_zampini     IS             rows,cols;
1246acdf38a7Sstefano_zampini     IS             irows,icols;
12471670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
12481670daf9Sstefano_zampini 
12491670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
12501670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
12511670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
12521670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
1253acdf38a7Sstefano_zampini     ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1254acdf38a7Sstefano_zampini     ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1255acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr);
1256acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr);
1257268753edSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
1258268753edSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1259acdf38a7Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
1260acdf38a7Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
12616104e0f1Sstefano_zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
12627dae84e0SHong Zhang     ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1263acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1264acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1265acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
12667c03b4e8SStefano Zampini     PetscFunctionReturn(0);
12677c03b4e8SStefano Zampini   }
1268b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1269b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
12703cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1271b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1272b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
12734099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1274b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1275b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1276b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1277b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1278b9ed4604SStefano Zampini   lb[0] = isseqdense;
1279b9ed4604SStefano Zampini   lb[1] = isseqaij;
1280b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1281b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1282b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1283b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1284b9ed4604SStefano Zampini #endif
1285b7ce53b6SStefano Zampini 
1286b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
12873927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
12883cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
1289b9ed4604SStefano Zampini     if (!isseqsbaij) {
1290b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1291b9ed4604SStefano Zampini     } else {
1292b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1293b9ed4604SStefano Zampini     }
1294d59cf9ebSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
12953927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1296b7ce53b6SStefano Zampini   } else {
12973cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1298b7ce53b6SStefano Zampini     /* some checks */
1299b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1300b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
13013cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
13026c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
13036c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
13046c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
13056c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
13066c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1307b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1308b7ce53b6SStefano Zampini   }
1309d9a9e74cSStefano Zampini 
1310b9ed4604SStefano Zampini   if (isseqsbaij) {
1311d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1312d9a9e74cSStefano Zampini   } else {
1313d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1314d9a9e74cSStefano Zampini     local_mat = matis->A;
1315d9a9e74cSStefano Zampini   }
1316686e3a49SStefano Zampini 
1317b7ce53b6SStefano Zampini   /* Set values */
1318ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1319b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
132065066ba5SStefano Zampini     PetscInt i,*dummy;
1321ecf5a873SStefano Zampini 
132265066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
132365066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
1324b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1325d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
132665066ba5SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
1327d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
132865066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
1329686e3a49SStefano Zampini   } else if (isseqaij) {
1330ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1331686e3a49SStefano Zampini     PetscBool done;
1332686e3a49SStefano Zampini 
1333d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1334938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1335d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1336686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1337ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1338686e3a49SStefano Zampini     }
1339d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1340938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1341d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1342686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1343ecf5a873SStefano Zampini     PetscInt i;
1344c0962df8SStefano Zampini 
1345686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1346686e3a49SStefano Zampini       PetscInt       j;
1347ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1348686e3a49SStefano Zampini 
1349ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1350ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1351ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1352686e3a49SStefano Zampini     }
1353b7ce53b6SStefano Zampini   }
1354b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1355d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1356b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1357b9ed4604SStefano Zampini   if (isseqdense) {
1358b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1359b7ce53b6SStefano Zampini   }
1360b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1361b7ce53b6SStefano Zampini }
1362b7ce53b6SStefano Zampini 
1363b7ce53b6SStefano Zampini /*@
1364b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1365b7ce53b6SStefano Zampini 
1366b7ce53b6SStefano Zampini   Input Parameter:
1367b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1368b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1369b7ce53b6SStefano Zampini 
1370b7ce53b6SStefano Zampini   Output Parameter:
1371b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1372b7ce53b6SStefano Zampini 
1373b7ce53b6SStefano Zampini   Level: developer
1374b7ce53b6SStefano Zampini 
1375eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1376b7ce53b6SStefano Zampini 
1377b7ce53b6SStefano Zampini .seealso: MATIS
1378b7ce53b6SStefano Zampini @*/
1379b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1380b7ce53b6SStefano Zampini {
1381b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1382b7ce53b6SStefano Zampini 
1383b7ce53b6SStefano Zampini   PetscFunctionBegin;
1384b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1385b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1386b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1387b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1388b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1389b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
13906c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1391b7ce53b6SStefano Zampini   }
1392b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1393b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1394b7ce53b6SStefano Zampini }
1395b7ce53b6SStefano Zampini 
1396ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1397ad6194a2SStefano Zampini {
1398ad6194a2SStefano Zampini   PetscErrorCode ierr;
1399ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1400ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1401ad6194a2SStefano Zampini   Mat            B,localmat;
1402ad6194a2SStefano Zampini 
1403ad6194a2SStefano Zampini   PetscFunctionBegin;
1404ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1405ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1406ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1407e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1408ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1409ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1410b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1411*b0f2910eSStefano Zampini   if (matis->sf) {
1412*b0f2910eSStefano Zampini     Mat_IS *bmatis = (Mat_IS*)(B->data);
1413*b0f2910eSStefano Zampini 
1414*b0f2910eSStefano Zampini     ierr       = PetscObjectReference((PetscObject)matis->sf);CHKERRQ(ierr);
1415*b0f2910eSStefano Zampini     bmatis->sf = matis->sf;
1416*b0f2910eSStefano Zampini     ierr       = PetscMalloc2(matis->sf->nroots,&bmatis->sf_rootdata,matis->sf->nleaves,&bmatis->sf_leafdata);CHKERRQ(ierr);
1417*b0f2910eSStefano Zampini     if (matis->sf != matis->csf) {
1418*b0f2910eSStefano Zampini       ierr        = PetscObjectReference((PetscObject)matis->csf);CHKERRQ(ierr);
1419*b0f2910eSStefano Zampini       bmatis->csf = matis->csf;
1420*b0f2910eSStefano Zampini       ierr        = PetscMalloc2(matis->csf->nroots,&bmatis->csf_rootdata,matis->csf->nleaves,&bmatis->csf_leafdata);CHKERRQ(ierr);
1421*b0f2910eSStefano Zampini     } else {
1422*b0f2910eSStefano Zampini       bmatis->csf          = bmatis->sf;
1423*b0f2910eSStefano Zampini       bmatis->csf_leafdata = bmatis->sf_leafdata;
1424*b0f2910eSStefano Zampini       bmatis->csf_rootdata = bmatis->sf_rootdata;
1425*b0f2910eSStefano Zampini     }
1426*b0f2910eSStefano Zampini   }
1427ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1428ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1429ad6194a2SStefano Zampini   *newmat = B;
1430ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1431ad6194a2SStefano Zampini }
1432ad6194a2SStefano Zampini 
1433a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
143469796d55SStefano Zampini {
143569796d55SStefano Zampini   PetscErrorCode ierr;
143669796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
143769796d55SStefano Zampini   PetscBool      local_sym;
143869796d55SStefano Zampini 
143969796d55SStefano Zampini   PetscFunctionBegin;
144069796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1441b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
144269796d55SStefano Zampini   PetscFunctionReturn(0);
144369796d55SStefano Zampini }
144469796d55SStefano Zampini 
1445a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
144669796d55SStefano Zampini {
144769796d55SStefano Zampini   PetscErrorCode ierr;
144869796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
144969796d55SStefano Zampini   PetscBool      local_sym;
145069796d55SStefano Zampini 
145169796d55SStefano Zampini   PetscFunctionBegin;
145269796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1453b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
145469796d55SStefano Zampini   PetscFunctionReturn(0);
145569796d55SStefano Zampini }
145669796d55SStefano Zampini 
145745471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
145845471136SStefano Zampini {
145945471136SStefano Zampini   PetscErrorCode ierr;
146045471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
146145471136SStefano Zampini   PetscBool      local_sym;
146245471136SStefano Zampini 
146345471136SStefano Zampini   PetscFunctionBegin;
146445471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
146545471136SStefano Zampini     *flg = PETSC_FALSE;
146645471136SStefano Zampini     PetscFunctionReturn(0);
146745471136SStefano Zampini   }
146845471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
146945471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
147045471136SStefano Zampini   PetscFunctionReturn(0);
147145471136SStefano Zampini }
147245471136SStefano Zampini 
1473a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1474b4319ba4SBarry Smith {
1475dfbe8321SBarry Smith   PetscErrorCode ierr;
1476b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1477b4319ba4SBarry Smith 
1478b4319ba4SBarry Smith   PetscFunctionBegin;
14796bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1480e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1481e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
14826bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
14836bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
14843fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1485a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1486a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1487a8116848SStefano Zampini   if (b->sf != b->csf) {
1488a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1489a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1490a8116848SStefano Zampini   }
149128f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
149228f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1493bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1494dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1495bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1496b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1497b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
14982e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1499cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1500b4319ba4SBarry Smith   PetscFunctionReturn(0);
1501b4319ba4SBarry Smith }
1502b4319ba4SBarry Smith 
1503a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1504b4319ba4SBarry Smith {
1505dfbe8321SBarry Smith   PetscErrorCode ierr;
1506b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1507b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1508b4319ba4SBarry Smith 
1509b4319ba4SBarry Smith   PetscFunctionBegin;
1510b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1511e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1512e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1513b4319ba4SBarry Smith 
1514b4319ba4SBarry Smith   /* multiply the local matrix */
1515b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1516b4319ba4SBarry Smith 
1517b4319ba4SBarry Smith   /* scatter product back into global memory */
15182dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1519e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1520e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1521b4319ba4SBarry Smith   PetscFunctionReturn(0);
1522b4319ba4SBarry Smith }
1523b4319ba4SBarry Smith 
1524a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15252e74eeadSLisandro Dalcin {
1526650997f4SStefano Zampini   Vec            temp_vec;
15272e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15282e74eeadSLisandro Dalcin 
15292e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1530650997f4SStefano Zampini   if (v3 != v2) {
1531650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1532650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1533650997f4SStefano Zampini   } else {
1534650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1535650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1536650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1537650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1538650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1539650997f4SStefano Zampini   }
15402e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15412e74eeadSLisandro Dalcin }
15422e74eeadSLisandro Dalcin 
1543a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
15442e74eeadSLisandro Dalcin {
15452e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
15462e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15472e74eeadSLisandro Dalcin 
1548e176bc59SStefano Zampini   PetscFunctionBegin;
15492e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1550e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1551e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15522e74eeadSLisandro Dalcin 
15532e74eeadSLisandro Dalcin   /* multiply the local matrix */
1554e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
15552e74eeadSLisandro Dalcin 
15562e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1557e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1558e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1559e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15602e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15612e74eeadSLisandro Dalcin }
15622e74eeadSLisandro Dalcin 
1563a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15642e74eeadSLisandro Dalcin {
1565650997f4SStefano Zampini   Vec            temp_vec;
15662e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15672e74eeadSLisandro Dalcin 
15682e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1569650997f4SStefano Zampini   if (v3 != v2) {
1570650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1571650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1572650997f4SStefano Zampini   } else {
1573650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1574650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1575650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1576650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1577650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1578650997f4SStefano Zampini   }
15792e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15802e74eeadSLisandro Dalcin }
15812e74eeadSLisandro Dalcin 
1582a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1583b4319ba4SBarry Smith {
1584b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1585dfbe8321SBarry Smith   PetscErrorCode ierr;
1586b4319ba4SBarry Smith   PetscViewer    sviewer;
1587ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1588b4319ba4SBarry Smith 
1589b4319ba4SBarry Smith   PetscFunctionBegin;
1590ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1591ee2491ecSStefano Zampini   if (isascii)  {
1592ee2491ecSStefano Zampini     PetscViewerFormat format;
1593ee2491ecSStefano Zampini 
1594ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1595ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1596ee2491ecSStefano Zampini   }
1597ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
15983f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1599b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
16003f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
16016e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1602b4319ba4SBarry Smith   PetscFunctionReturn(0);
1603b4319ba4SBarry Smith }
1604b4319ba4SBarry Smith 
1605a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1606b4319ba4SBarry Smith {
1607dfbe8321SBarry Smith   PetscErrorCode ierr;
1608e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1609b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1610b4319ba4SBarry Smith   IS             from,to;
1611e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1612b4319ba4SBarry Smith 
1613b4319ba4SBarry Smith   PetscFunctionBegin;
1614784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1615e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
16163bbff08aSStefano Zampini   /* Destroy any previous data */
161770cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
161870cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
16193fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1620e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1621e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
16221c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
1623872cf891SStefano Zampini   if (is->csf != is->sf) {
1624872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
1625872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
1626872cf891SStefano Zampini   }
162728f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
162828f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
16293bbff08aSStefano Zampini 
16303bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1631fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1632fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1633e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1634e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1635e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1636e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
16376625354bSStefano Zampini   /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */
16386625354bSStefano Zampini   if (rmapping != cmapping && A->rmap->N == A->cmap->N) {
16396625354bSStefano Zampini     PetscBool same,gsame;
16406625354bSStefano Zampini 
16416625354bSStefano Zampini     same = PETSC_FALSE;
16426625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
16436625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
16446625354bSStefano Zampini 
16456625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
16466625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
16476625354bSStefano Zampini       ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr);
16486625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
16496625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
16506625354bSStefano Zampini     }
16516625354bSStefano Zampini     ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
16526625354bSStefano Zampini     if (gsame) cmapping = rmapping;
16536625354bSStefano Zampini   }
16546625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
16556625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
16566625354bSStefano Zampini 
16576625354bSStefano Zampini   /* Create the local matrix A */
1658f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1659e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1660e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1661e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1662ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1663ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1664b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1665c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
1666c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
1667b4319ba4SBarry Smith 
1668f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1669b4319ba4SBarry Smith     /* Create the local work vectors */
16703bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1671b4319ba4SBarry Smith 
1672e176bc59SStefano Zampini     /* setup the global to local scatters */
1673e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1674e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1675784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1676e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1677e176bc59SStefano Zampini     if (rmapping != cmapping) {
1678e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1679e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1680e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1681e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1682e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1683e176bc59SStefano Zampini     } else {
1684e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1685e176bc59SStefano Zampini       is->cctx = is->rctx;
1686e176bc59SStefano Zampini     }
16873fd1c9e7SStefano Zampini 
16883fd1c9e7SStefano Zampini     /* interface counter vector (local) */
16893fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
16903fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
16913fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16923fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16933fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16943fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16953fd1c9e7SStefano Zampini 
16963fd1c9e7SStefano Zampini     /* free workspace */
1697e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1698e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
16996bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
17006bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1701f26d0771SStefano Zampini   }
170248ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1703b4319ba4SBarry Smith   PetscFunctionReturn(0);
1704b4319ba4SBarry Smith }
1705b4319ba4SBarry Smith 
1706a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
17072e74eeadSLisandro Dalcin {
17082e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
17092e74eeadSLisandro Dalcin   PetscErrorCode ierr;
171097563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
171197563a80SStefano Zampini   PetscInt       i,zm,zn;
171297563a80SStefano Zampini #endif
1713f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
17142e74eeadSLisandro Dalcin 
17152e74eeadSLisandro Dalcin   PetscFunctionBegin;
17162e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1717f26d0771SStefano 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);
171897563a80SStefano Zampini   /* count negative indices */
171997563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
172097563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
17212e74eeadSLisandro Dalcin #endif
172297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
172397563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
172497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
172597563a80SStefano Zampini   /* count negative indices (should be the same as before) */
172697563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
172797563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
1728b4f971dfSStefano 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");
1729b4f971dfSStefano 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");
173097563a80SStefano Zampini #endif
17312e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
17322e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
17332e74eeadSLisandro Dalcin }
17342e74eeadSLisandro Dalcin 
1735a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
173697563a80SStefano Zampini {
173797563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
173897563a80SStefano Zampini   PetscErrorCode ierr;
173997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
174097563a80SStefano Zampini   PetscInt       i,zm,zn;
174197563a80SStefano Zampini #endif
1742f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
174397563a80SStefano Zampini 
174497563a80SStefano Zampini   PetscFunctionBegin;
174597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1746f26d0771SStefano 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);
174797563a80SStefano Zampini   /* count negative indices */
174897563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
174997563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
175097563a80SStefano Zampini #endif
175197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
175297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
175397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
175497563a80SStefano Zampini   /* count negative indices (should be the same as before) */
175597563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
175697563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
1757b4f971dfSStefano 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");
1758b4f971dfSStefano 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");
175997563a80SStefano Zampini #endif
1760d59cf9ebSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
176197563a80SStefano Zampini   PetscFunctionReturn(0);
176297563a80SStefano Zampini }
176397563a80SStefano Zampini 
1764a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1765b4319ba4SBarry Smith {
1766dfbe8321SBarry Smith   PetscErrorCode ierr;
1767b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1768b4319ba4SBarry Smith 
1769b4319ba4SBarry Smith   PetscFunctionBegin;
1770b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
1771872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1772872cf891SStefano Zampini   } else {
1773b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1774872cf891SStefano Zampini   }
1775b4319ba4SBarry Smith   PetscFunctionReturn(0);
1776b4319ba4SBarry Smith }
1777b4319ba4SBarry Smith 
1778a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1779f0006bf2SLisandro Dalcin {
1780f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1781f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1782f0006bf2SLisandro Dalcin 
1783f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1784b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
1785b4f971dfSStefano Zampini #if defined(PETSC_USE_DEBUG)
1786b4f971dfSStefano Zampini     PetscInt ibs,bs;
1787b4f971dfSStefano Zampini 
1788b4f971dfSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
1789b4f971dfSStefano Zampini     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
1790b4f971dfSStefano Zampini     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
1791b4f971dfSStefano Zampini #endif
1792b4f971dfSStefano Zampini     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1793b4f971dfSStefano Zampini   } else {
1794f0006bf2SLisandro Dalcin     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1795b4f971dfSStefano Zampini   }
1796f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1797f0006bf2SLisandro Dalcin }
1798f0006bf2SLisandro Dalcin 
1799f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1800f0ae7da4SStefano Zampini {
1801f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1802f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1803f0ae7da4SStefano Zampini 
1804f0ae7da4SStefano Zampini   PetscFunctionBegin;
1805f0ae7da4SStefano Zampini   if (!n) {
1806f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1807f0ae7da4SStefano Zampini   } else {
1808f0ae7da4SStefano Zampini     PetscInt i;
1809f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1810f0ae7da4SStefano Zampini 
1811f0ae7da4SStefano Zampini     if (columns) {
1812f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1813f0ae7da4SStefano Zampini     } else {
1814f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1815f0ae7da4SStefano Zampini     }
1816f0ae7da4SStefano Zampini     if (diag != 0.) {
1817f0ae7da4SStefano Zampini       const PetscScalar *array;
1818f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1819f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1820f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1821f0ae7da4SStefano Zampini       }
1822f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1823f0ae7da4SStefano Zampini     }
1824f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1825f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1826f0ae7da4SStefano Zampini   }
1827f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1828f0ae7da4SStefano Zampini }
1829f0ae7da4SStefano Zampini 
1830f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
18312e74eeadSLisandro Dalcin {
18326e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
18336e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
18346e520ac8SStefano Zampini   PetscInt       *lrows;
18352e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18362e74eeadSLisandro Dalcin 
18372e74eeadSLisandro Dalcin   PetscFunctionBegin;
1838f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1839f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1840f0ae7da4SStefano Zampini     PetscBool cong;
184126b0207aSStefano Zampini 
1842f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
184326b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
1844268753edSStefano 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");
1845268753edSStefano 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");
1846268753edSStefano 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");
1847f0ae7da4SStefano Zampini   }
1848f0ae7da4SStefano Zampini #endif
18496e520ac8SStefano Zampini   /* get locally owned rows */
1850f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
18516e520ac8SStefano Zampini   /* fix right hand side if needed */
18526e520ac8SStefano Zampini   if (x && b) {
18536e520ac8SStefano Zampini     const PetscScalar *xx;
18546e520ac8SStefano Zampini     PetscScalar       *bb;
18556e520ac8SStefano Zampini 
18566e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
18576e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
18586e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
18596e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
18606e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
18612e74eeadSLisandro Dalcin   }
18626e520ac8SStefano Zampini   /* get rows associated to the local matrices */
18633d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
18646e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
18656e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
18666e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
18676e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
18686e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18696e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18706e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18716e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
18726e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1873f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
18746e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18752e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18762e74eeadSLisandro Dalcin }
18772e74eeadSLisandro Dalcin 
1878f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1879b4319ba4SBarry Smith {
1880dfbe8321SBarry Smith   PetscErrorCode ierr;
1881b4319ba4SBarry Smith 
1882b4319ba4SBarry Smith   PetscFunctionBegin;
1883f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1884f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1885f0ae7da4SStefano Zampini }
18862205254eSKarl Rupp 
1887f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1888f0ae7da4SStefano Zampini {
1889f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1890f0ae7da4SStefano Zampini 
1891f0ae7da4SStefano Zampini   PetscFunctionBegin;
1892f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1893b4319ba4SBarry Smith   PetscFunctionReturn(0);
1894b4319ba4SBarry Smith }
1895b4319ba4SBarry Smith 
1896a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1897b4319ba4SBarry Smith {
1898b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1899dfbe8321SBarry Smith   PetscErrorCode ierr;
1900b4319ba4SBarry Smith 
1901b4319ba4SBarry Smith   PetscFunctionBegin;
1902b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1903b4319ba4SBarry Smith   PetscFunctionReturn(0);
1904b4319ba4SBarry Smith }
1905b4319ba4SBarry Smith 
1906a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1907b4319ba4SBarry Smith {
1908b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1909dfbe8321SBarry Smith   PetscErrorCode ierr;
1910b4319ba4SBarry Smith 
1911b4319ba4SBarry Smith   PetscFunctionBegin;
1912b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1913872cf891SStefano Zampini   /* fix for local empty rows/cols */
1914872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
1915872cf891SStefano Zampini     Mat                    newlA;
1916872cf891SStefano Zampini     ISLocalToGlobalMapping l2g;
1917872cf891SStefano Zampini     IS                     tis;
1918872cf891SStefano Zampini     const PetscScalar      *v;
1919872cf891SStefano Zampini     PetscInt               i,n,cf,*loce,*locf;
1920872cf891SStefano Zampini     PetscBool              sym;
1921872cf891SStefano Zampini 
1922872cf891SStefano Zampini     ierr = MatGetRowMaxAbs(is->A,is->y,NULL);CHKERRQ(ierr);
1923872cf891SStefano Zampini     ierr = MatIsSymmetric(is->A,PETSC_SMALL,&sym);CHKERRQ(ierr);
1924872cf891SStefano Zampini     if (!sym) SETERRQ(PetscObjectComm((PetscObject)is->A),PETSC_ERR_SUP,"Not yet implemented for unsymmetric case");
1925872cf891SStefano Zampini     ierr = VecGetLocalSize(is->y,&n);CHKERRQ(ierr);
1926872cf891SStefano Zampini     ierr = PetscMalloc1(n,&loce);CHKERRQ(ierr);
1927872cf891SStefano Zampini     ierr = PetscMalloc1(n,&locf);CHKERRQ(ierr);
1928872cf891SStefano Zampini     ierr = VecGetArrayRead(is->y,&v);CHKERRQ(ierr);
1929872cf891SStefano Zampini     for (i=0,cf=0;i<n;i++) {
1930872cf891SStefano Zampini       if (v[i] == 0.0) {
1931872cf891SStefano Zampini         loce[i] = -1;
1932872cf891SStefano Zampini       } else {
1933872cf891SStefano Zampini         loce[i]    = cf;
1934872cf891SStefano Zampini         locf[cf++] = i;
1935872cf891SStefano Zampini       }
1936872cf891SStefano Zampini     }
1937872cf891SStefano Zampini     ierr = VecRestoreArrayRead(is->y,&v);CHKERRQ(ierr);
1938872cf891SStefano Zampini     /* extract valid submatrix */
1939872cf891SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A),cf,locf,PETSC_USE_POINTER,&tis);CHKERRQ(ierr);
1940e5b89577SStefano Zampini     ierr = MatCreateSubMatrix(is->A,tis,tis,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
1941872cf891SStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
1942872cf891SStefano Zampini     /* attach local l2g map for successive calls of MatSetValues */
1943872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is->A),1,n,loce,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
1944872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(newlA,l2g,l2g);CHKERRQ(ierr);
1945872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
1946872cf891SStefano Zampini     /* attach new global l2g map */
1947872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,cf,locf,locf);CHKERRQ(ierr);
1948872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,cf,locf,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
1949872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(A,l2g,l2g);CHKERRQ(ierr);
1950872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
1951872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
1952872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
1953872cf891SStefano Zampini   }
1954872cf891SStefano Zampini   is->locempty = PETSC_FALSE;
1955b4319ba4SBarry Smith   PetscFunctionReturn(0);
1956b4319ba4SBarry Smith }
1957b4319ba4SBarry Smith 
1958a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1959b4319ba4SBarry Smith {
1960b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1961b4319ba4SBarry Smith 
1962b4319ba4SBarry Smith   PetscFunctionBegin;
1963b4319ba4SBarry Smith   *local = is->A;
1964b4319ba4SBarry Smith   PetscFunctionReturn(0);
1965b4319ba4SBarry Smith }
1966b4319ba4SBarry Smith 
19673b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
19683b3b1effSJed Brown {
19693b3b1effSJed Brown   PetscFunctionBegin;
19703b3b1effSJed Brown   *local = NULL;
19713b3b1effSJed Brown   PetscFunctionReturn(0);
19723b3b1effSJed Brown }
19733b3b1effSJed Brown 
1974b4319ba4SBarry Smith /*@
1975b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1976b4319ba4SBarry Smith 
1977b4319ba4SBarry Smith   Input Parameter:
1978b4319ba4SBarry Smith .  mat - the matrix
1979b4319ba4SBarry Smith 
1980b4319ba4SBarry Smith   Output Parameter:
1981eb82efa4SStefano Zampini .  local - the local matrix
1982b4319ba4SBarry Smith 
1983b4319ba4SBarry Smith   Level: advanced
1984b4319ba4SBarry Smith 
1985b4319ba4SBarry Smith   Notes:
1986b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1987b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1988b4319ba4SBarry Smith   of the MatSetValues() operation.
1989b4319ba4SBarry Smith 
19903b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
199196a6f129SJed Brown 
1992b4319ba4SBarry Smith .seealso: MATIS
1993b4319ba4SBarry Smith @*/
19947087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1995b4319ba4SBarry Smith {
19964ac538c5SBarry Smith   PetscErrorCode ierr;
1997b4319ba4SBarry Smith 
1998b4319ba4SBarry Smith   PetscFunctionBegin;
19990700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2000b4319ba4SBarry Smith   PetscValidPointer(local,2);
20014ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
2002b4319ba4SBarry Smith   PetscFunctionReturn(0);
2003b4319ba4SBarry Smith }
2004b4319ba4SBarry Smith 
20053b3b1effSJed Brown /*@
20063b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
20073b3b1effSJed Brown 
20083b3b1effSJed Brown   Input Parameter:
20093b3b1effSJed Brown .  mat - the matrix
20103b3b1effSJed Brown 
20113b3b1effSJed Brown   Output Parameter:
20123b3b1effSJed Brown .  local - the local matrix
20133b3b1effSJed Brown 
20143b3b1effSJed Brown   Level: advanced
20153b3b1effSJed Brown 
20163b3b1effSJed Brown .seealso: MATIS
20173b3b1effSJed Brown @*/
20183b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
20193b3b1effSJed Brown {
20203b3b1effSJed Brown   PetscErrorCode ierr;
20213b3b1effSJed Brown 
20223b3b1effSJed Brown   PetscFunctionBegin;
20233b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
20243b3b1effSJed Brown   PetscValidPointer(local,2);
20253b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
20263b3b1effSJed Brown   PetscFunctionReturn(0);
20273b3b1effSJed Brown }
20283b3b1effSJed Brown 
2029a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
20303b03a366Sstefano_zampini {
20313b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
20323b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
20333b03a366Sstefano_zampini   PetscErrorCode ierr;
20343b03a366Sstefano_zampini 
20353b03a366Sstefano_zampini   PetscFunctionBegin;
20364e4c7dbeSStefano Zampini   if (is->A) {
20373b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
20383b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2039f0ae7da4SStefano 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);
20404e4c7dbeSStefano Zampini   }
20413b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
20423b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
20433b03a366Sstefano_zampini   is->A = local;
20443b03a366Sstefano_zampini   PetscFunctionReturn(0);
20453b03a366Sstefano_zampini }
20463b03a366Sstefano_zampini 
20473b03a366Sstefano_zampini /*@
2048eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
20493b03a366Sstefano_zampini 
20503b03a366Sstefano_zampini   Input Parameter:
20513b03a366Sstefano_zampini .  mat - the matrix
2052eb82efa4SStefano Zampini .  local - the local matrix
20533b03a366Sstefano_zampini 
20543b03a366Sstefano_zampini   Output Parameter:
20553b03a366Sstefano_zampini 
20563b03a366Sstefano_zampini   Level: advanced
20573b03a366Sstefano_zampini 
20583b03a366Sstefano_zampini   Notes:
20593b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
20603b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
20613b03a366Sstefano_zampini 
20623b03a366Sstefano_zampini .seealso: MATIS
20633b03a366Sstefano_zampini @*/
20643b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
20653b03a366Sstefano_zampini {
20663b03a366Sstefano_zampini   PetscErrorCode ierr;
20673b03a366Sstefano_zampini 
20683b03a366Sstefano_zampini   PetscFunctionBegin;
20693b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2070b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
20713b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
20723b03a366Sstefano_zampini   PetscFunctionReturn(0);
20733b03a366Sstefano_zampini }
20743b03a366Sstefano_zampini 
2075a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
20766726f965SBarry Smith {
20776726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
20786726f965SBarry Smith   PetscErrorCode ierr;
20796726f965SBarry Smith 
20806726f965SBarry Smith   PetscFunctionBegin;
20816726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
20826726f965SBarry Smith   PetscFunctionReturn(0);
20836726f965SBarry Smith }
20846726f965SBarry Smith 
2085a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
20862e74eeadSLisandro Dalcin {
20872e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20882e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20892e74eeadSLisandro Dalcin 
20902e74eeadSLisandro Dalcin   PetscFunctionBegin;
20912e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
20922e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20932e74eeadSLisandro Dalcin }
20942e74eeadSLisandro Dalcin 
2095a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
20962e74eeadSLisandro Dalcin {
20972e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20982e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20992e74eeadSLisandro Dalcin 
21002e74eeadSLisandro Dalcin   PetscFunctionBegin;
21012e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
2102e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
21032e74eeadSLisandro Dalcin 
21042e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
21052e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
2106e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2107e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21082e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
21092e74eeadSLisandro Dalcin }
21102e74eeadSLisandro Dalcin 
2111a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
21126726f965SBarry Smith {
21136726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
21146726f965SBarry Smith   PetscErrorCode ierr;
21156726f965SBarry Smith 
21166726f965SBarry Smith   PetscFunctionBegin;
21174e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
21186726f965SBarry Smith   PetscFunctionReturn(0);
21196726f965SBarry Smith }
21206726f965SBarry Smith 
2121f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
2122f26d0771SStefano Zampini {
2123f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
2124f26d0771SStefano Zampini   Mat_IS         *x;
2125f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2126f26d0771SStefano Zampini   PetscBool      ismatis;
2127f26d0771SStefano Zampini #endif
2128f26d0771SStefano Zampini   PetscErrorCode ierr;
2129f26d0771SStefano Zampini 
2130f26d0771SStefano Zampini   PetscFunctionBegin;
2131f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2132f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
2133f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
2134f26d0771SStefano Zampini #endif
2135f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
2136f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
2137f26d0771SStefano Zampini   PetscFunctionReturn(0);
2138f26d0771SStefano Zampini }
2139f26d0771SStefano Zampini 
2140f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
2141f26d0771SStefano Zampini {
2142f26d0771SStefano Zampini   Mat                    lA;
2143f26d0771SStefano Zampini   Mat_IS                 *matis;
2144f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2145f26d0771SStefano Zampini   IS                     is;
2146f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
2147f26d0771SStefano Zampini   PetscInt               nrg;
2148f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
2149f26d0771SStefano Zampini   PetscErrorCode         ierr;
2150f26d0771SStefano Zampini 
2151f26d0771SStefano Zampini   PetscFunctionBegin;
2152f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2153f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
2154f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
2155f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
2156f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2157f0ae7da4SStefano 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);
2158f26d0771SStefano Zampini #endif
2159f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
2160f26d0771SStefano Zampini   /* map from [0,nrl) to row */
2161f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
2162f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2163f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
2164f26d0771SStefano Zampini #else
2165f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
2166f26d0771SStefano Zampini #endif
2167f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
2168f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2169f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2170f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2171f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
2172f26d0771SStefano Zampini   /* compute new l2g map for columns */
2173f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2174f26d0771SStefano Zampini     const PetscInt *cg,*cl;
2175f26d0771SStefano Zampini     PetscInt       ncg;
2176f26d0771SStefano Zampini     PetscInt       ncl;
2177f26d0771SStefano Zampini 
2178f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2179f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2180f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2181f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2182f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2183f0ae7da4SStefano 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);
2184f26d0771SStefano Zampini #endif
2185f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2186f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2187f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2188f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2189f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2190f26d0771SStefano Zampini #else
2191f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2192f26d0771SStefano Zampini #endif
2193f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2194f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2195f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2196f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2197f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2198f26d0771SStefano Zampini   } else {
2199f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2200f26d0771SStefano Zampini     cl2g = rl2g;
2201f26d0771SStefano Zampini   }
2202f26d0771SStefano Zampini   /* create the MATIS submatrix */
2203f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2204f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2205f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2206f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2207b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2208f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2209f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2210f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2211f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2212f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2213f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2214f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2215f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2216f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2217f26d0771SStefano Zampini   /* remove unsupported ops */
2218f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2219f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2220f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2221f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2222f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2223f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2224f26d0771SStefano Zampini   PetscFunctionReturn(0);
2225f26d0771SStefano Zampini }
2226f26d0771SStefano Zampini 
2227872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
2228872cf891SStefano Zampini {
2229872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
2230872cf891SStefano Zampini   PetscErrorCode ierr;
2231872cf891SStefano Zampini 
2232872cf891SStefano Zampini   PetscFunctionBegin;
2233872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
2234872cf891SStefano Zampini   ierr = PetscObjectOptionsBegin((PetscObject)A);
2235872cf891SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns",NULL,a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
2236872cf891SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
2237872cf891SStefano Zampini   PetscFunctionReturn(0);
2238872cf891SStefano Zampini }
2239872cf891SStefano Zampini 
2240284134d9SBarry Smith /*@
22413c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2242284134d9SBarry Smith        process but not across processes.
2243284134d9SBarry Smith 
2244284134d9SBarry Smith    Input Parameters:
2245284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2246e176bc59SStefano Zampini .     bs      - block size of the matrix
2247df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2248e176bc59SStefano Zampini .     rmap    - local to global map for rows
2249e176bc59SStefano Zampini -     cmap    - local to global map for cols
2250284134d9SBarry Smith 
2251284134d9SBarry Smith    Output Parameter:
2252284134d9SBarry Smith .    A - the resulting matrix
2253284134d9SBarry Smith 
22548e6c10adSSatish Balay    Level: advanced
22558e6c10adSSatish Balay 
22563c212e90SHong Zhang    Notes: See MATIS for more details.
22576fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
22586fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
22593c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2260284134d9SBarry Smith 
2261284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2262284134d9SBarry Smith @*/
2263e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2264284134d9SBarry Smith {
2265284134d9SBarry Smith   PetscErrorCode ierr;
2266284134d9SBarry Smith 
2267284134d9SBarry Smith   PetscFunctionBegin;
22686fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2269284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2270284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
22716fdf41d1SStefano Zampini   if (bs > 0) {
2272284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
22736fdf41d1SStefano Zampini   }
2274284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2275e176bc59SStefano Zampini   if (rmap && cmap) {
2276e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2277e176bc59SStefano Zampini   } else if (!rmap) {
2278e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2279e176bc59SStefano Zampini   } else {
2280e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2281e176bc59SStefano Zampini   }
2282284134d9SBarry Smith   PetscFunctionReturn(0);
2283284134d9SBarry Smith }
2284284134d9SBarry Smith 
2285b4319ba4SBarry Smith /*MC
2286f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2287b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2288b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2289b4319ba4SBarry Smith    product is handled "implicitly".
2290b4319ba4SBarry Smith 
2291b4319ba4SBarry Smith    Operations Provided:
22926726f965SBarry Smith +  MatMult()
22932e74eeadSLisandro Dalcin .  MatMultAdd()
22942e74eeadSLisandro Dalcin .  MatMultTranspose()
22952e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
22966726f965SBarry Smith .  MatZeroEntries()
22976726f965SBarry Smith .  MatSetOption()
22982e74eeadSLisandro Dalcin .  MatZeroRows()
22992e74eeadSLisandro Dalcin .  MatSetValues()
230097563a80SStefano Zampini .  MatSetValuesBlocked()
23016726f965SBarry Smith .  MatSetValuesLocal()
230297563a80SStefano Zampini .  MatSetValuesBlockedLocal()
23032e74eeadSLisandro Dalcin .  MatScale()
23042e74eeadSLisandro Dalcin .  MatGetDiagonal()
23052b404112SStefano Zampini .  MatMissingDiagonal()
23062b404112SStefano Zampini .  MatDuplicate()
23072b404112SStefano Zampini .  MatCopy()
2308f26d0771SStefano Zampini .  MatAXPY()
23097dae84e0SHong Zhang .  MatCreateSubMatrix()
2310f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2311d7f69cd0SStefano Zampini .  MatTranspose()
23126726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2313b4319ba4SBarry Smith 
2314b4319ba4SBarry Smith    Options Database Keys:
2315b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2316b4319ba4SBarry Smith 
2317b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
2318b4319ba4SBarry Smith 
2319b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2320b4319ba4SBarry Smith 
2321b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2322eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2323b4319ba4SBarry Smith 
2324b4319ba4SBarry Smith   Level: advanced
2325b4319ba4SBarry Smith 
2326f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2327b4319ba4SBarry Smith 
2328b4319ba4SBarry Smith M*/
2329b4319ba4SBarry Smith 
23308cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2331b4319ba4SBarry Smith {
2332dfbe8321SBarry Smith   PetscErrorCode ierr;
2333b4319ba4SBarry Smith   Mat_IS         *b;
2334b4319ba4SBarry Smith 
2335b4319ba4SBarry Smith   PetscFunctionBegin;
2336b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2337b4319ba4SBarry Smith   A->data = (void*)b;
2338b4319ba4SBarry Smith 
2339e176bc59SStefano Zampini   /* matrix ops */
2340e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2341b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
23422e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
23432e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
23442e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2345b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2346b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
23472e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
234898921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2349b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2350f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
23512e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2352f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2353b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2354b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2355b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
23566726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
23572e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
23582e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
23596726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
236069796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
236169796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
236245471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2363ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
23646bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
23652b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2366659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
23677dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
2368f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
23693fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
23703fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2371d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
23727fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
2373ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
2374872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
2375b4319ba4SBarry Smith 
2376b7ce53b6SStefano Zampini   /* special MATIS functions */
2377bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
23783b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
2379bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2380b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
23812e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2382cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
238317667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2384b4319ba4SBarry Smith   PetscFunctionReturn(0);
2385b4319ba4SBarry Smith }
2386