xref: /petsc/src/mat/impls/is/matis.c (revision 0f2f62c7de55b43174e0e4060b361db8c39945d6)
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
15f26d0771SStefano Zampini 
165b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
175b003df0Sstefano_zampini {
185b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
195b003df0Sstefano_zampini   PetscInt         i;
205b003df0Sstefano_zampini   PetscErrorCode   ierr;
215b003df0Sstefano_zampini 
225b003df0Sstefano_zampini   PetscFunctionBeginUser;
235b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
245b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
255b003df0Sstefano_zampini   }
265b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
275b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
285b003df0Sstefano_zampini   }
295b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
305b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
315b003df0Sstefano_zampini   PetscFunctionReturn(0);
325b003df0Sstefano_zampini }
33a72627d2SStefano Zampini 
345b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyArray_Private(void *ptr)
357fa8f2d3SStefano Zampini {
366989cf23SStefano Zampini   PetscErrorCode ierr;
376989cf23SStefano Zampini 
386989cf23SStefano Zampini   PetscFunctionBeginUser;
396989cf23SStefano Zampini   ierr = PetscFree(ptr);CHKERRQ(ierr);
406989cf23SStefano Zampini   PetscFunctionReturn(0);
416989cf23SStefano Zampini }
426989cf23SStefano Zampini 
436989cf23SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
446989cf23SStefano Zampini {
456989cf23SStefano Zampini   Mat_MPIAIJ             *aij  = (Mat_MPIAIJ*)A->data;
466989cf23SStefano Zampini   Mat_SeqAIJ             *diag = (Mat_SeqAIJ*)(aij->A->data);
476989cf23SStefano Zampini   Mat_SeqAIJ             *offd = (Mat_SeqAIJ*)(aij->B->data);
486989cf23SStefano Zampini   Mat                    lA;
496989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
506989cf23SStefano Zampini   IS                     is;
516989cf23SStefano Zampini   MPI_Comm               comm;
526989cf23SStefano Zampini   void                   *ptrs[2];
536989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
546989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
556989cf23SStefano Zampini   PetscInt               *di,*dj,*oi,*oj;
566989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
57e363d98aSStefano Zampini   PetscInt               lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
586989cf23SStefano Zampini   PetscErrorCode         ierr;
596989cf23SStefano Zampini 
606989cf23SStefano Zampini   PetscFunctionBeginUser;
616989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
626989cf23SStefano Zampini   if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present");
636989cf23SStefano Zampini 
646989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
656989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
666989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
676989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
686989cf23SStefano Zampini   di   = diag->i;
696989cf23SStefano Zampini   dj   = diag->j;
706989cf23SStefano Zampini   dd   = diag->a;
716989cf23SStefano Zampini   oc   = aij->B->cmap->n;
726989cf23SStefano Zampini   oi   = offd->i;
736989cf23SStefano Zampini   oj   = offd->j;
746989cf23SStefano Zampini   od   = offd->a;
756989cf23SStefano Zampini   nnz  = diag->i[dr] + offd->i[dr];
766989cf23SStefano Zampini 
776989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
786989cf23SStefano Zampini   ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
796989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
806989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
81e363d98aSStefano Zampini   if (dr) {
826989cf23SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
836989cf23SStefano Zampini     for (i=0; i<dc; i++) aux[i]    = i+stc;
846989cf23SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i];
856989cf23SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
86e363d98aSStefano Zampini     lc   = dc+oc;
87e363d98aSStefano Zampini   } else {
88e363d98aSStefano Zampini     ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
89e363d98aSStefano Zampini     lc   = 0;
90e363d98aSStefano Zampini   }
916989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
926989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
936989cf23SStefano Zampini 
946989cf23SStefano Zampini   /* create MATIS object */
956989cf23SStefano Zampini   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
966989cf23SStefano Zampini   ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
976989cf23SStefano Zampini   ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
986989cf23SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
996989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1006989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1016989cf23SStefano Zampini 
1026989cf23SStefano Zampini   /* merge local matrices */
1036989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
1046989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
1056989cf23SStefano Zampini   ii   = aux;
1066989cf23SStefano Zampini   jj   = aux+dr+1;
1076989cf23SStefano Zampini   aa   = data;
1086989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
1096989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
1106989cf23SStefano Zampini   {
1116989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
1126989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
1136989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
1146989cf23SStefano Zampini   }
1156989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
1166989cf23SStefano Zampini   ii   = aux;
1176989cf23SStefano Zampini   jj   = aux+dr+1;
1186989cf23SStefano Zampini   aa   = data;
119e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
1206989cf23SStefano Zampini 
1216989cf23SStefano Zampini   /* create containers to destroy the data */
1226989cf23SStefano Zampini   ptrs[0] = aux;
1236989cf23SStefano Zampini   ptrs[1] = data;
1246989cf23SStefano Zampini   for (i=0; i<2; i++) {
1256989cf23SStefano Zampini     PetscContainer c;
1266989cf23SStefano Zampini 
1276989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
1286989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
1295b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyArray_Private);CHKERRQ(ierr);
1306989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
1316989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
1326989cf23SStefano Zampini   }
1336989cf23SStefano Zampini 
1346989cf23SStefano Zampini   /* finalize matrix */
1356989cf23SStefano Zampini   ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
1366989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
1376989cf23SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1386989cf23SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1396989cf23SStefano Zampini   PetscFunctionReturn(0);
1406989cf23SStefano Zampini }
1416989cf23SStefano Zampini 
142cf0a3239SStefano Zampini /*@
1433d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
144cf0a3239SStefano Zampini 
145cf0a3239SStefano Zampini    Collective on MPI_Comm
146cf0a3239SStefano Zampini 
147cf0a3239SStefano Zampini    Input Parameters:
148cf0a3239SStefano Zampini +  A - the matrix
149cf0a3239SStefano Zampini 
150cf0a3239SStefano Zampini    Level: advanced
151cf0a3239SStefano Zampini 
1523d996552SStefano Zampini    Notes: This function does not need to be called by the user.
153cf0a3239SStefano Zampini 
154cf0a3239SStefano Zampini .keywords: matrix
155cf0a3239SStefano Zampini 
156cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
157cf0a3239SStefano Zampini @*/
158cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
159cf0a3239SStefano Zampini {
1607fa8f2d3SStefano Zampini   PetscErrorCode ierr;
1617fa8f2d3SStefano Zampini 
1627fa8f2d3SStefano Zampini   PetscFunctionBegin;
163cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
164cf0a3239SStefano Zampini   PetscValidType(A,1);
165cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
1667fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
1677fa8f2d3SStefano Zampini }
1687fa8f2d3SStefano Zampini 
1695e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1705e3038f0Sstefano_zampini {
1715e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
1725e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
1735e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
1745e3038f0Sstefano_zampini   MPI_Comm               comm;
1755b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
1765b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
1779e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
1785e3038f0Sstefano_zampini   PetscErrorCode         ierr;
1795e3038f0Sstefano_zampini 
1805e3038f0Sstefano_zampini   PetscFunctionBeginUser;
1815e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
1825e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
1835e3038f0Sstefano_zampini   rnest  = NULL;
1845e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
1855e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
1865e3038f0Sstefano_zampini 
1875e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1885e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
1895e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
1905e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
1915e3038f0Sstefano_zampini     if (isnest) {
1925e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
1935e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
1945e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
1955e3038f0Sstefano_zampini     }
1965e3038f0Sstefano_zampini   }
1975e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1985b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
1999e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
2005e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
2019e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
2025e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
2035e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2045e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2055e3038f0Sstefano_zampini       PetscBool ismatis;
2069e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
2075e3038f0Sstefano_zampini 
2085e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
2095e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2105e3038f0Sstefano_zampini 
2115e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
2129e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
2139e7b2b25Sstefano_zampini       if (istrans[ij]) {
2149e7b2b25Sstefano_zampini         Mat T,lT;
2159e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2169e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
2179e7b2b25Sstefano_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);
2189e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
2199e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
2209e7b2b25Sstefano_zampini       } else {
2215e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
2225e3038f0Sstefano_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);
2239e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
2249e7b2b25Sstefano_zampini       }
2255e3038f0Sstefano_zampini 
2265e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
2275e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
2289e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
2295e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
2305e3038f0Sstefano_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);
2315e3038f0Sstefano_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);
2325e3038f0Sstefano_zampini       lr[i] = l1;
2335e3038f0Sstefano_zampini       lc[j] = l2;
2345e3038f0Sstefano_zampini 
2355e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
2365e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
2375e3038f0Sstefano_zampini     }
2385e3038f0Sstefano_zampini   }
2395e3038f0Sstefano_zampini 
2405e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
2415e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
2425e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2435e3038f0Sstefano_zampini     rl2g = NULL;
2445e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2455e3038f0Sstefano_zampini       PetscInt n1,n2;
2465e3038f0Sstefano_zampini 
2475e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2489e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
2499e7b2b25Sstefano_zampini         Mat T;
2509e7b2b25Sstefano_zampini 
2519e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2529e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
2539e7b2b25Sstefano_zampini       } else {
2545e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
2559e7b2b25Sstefano_zampini       }
2565e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2575e3038f0Sstefano_zampini       if (!n1) continue;
2585e3038f0Sstefano_zampini       if (!rl2g) {
2595e3038f0Sstefano_zampini         rl2g = cl2g;
2605e3038f0Sstefano_zampini       } else {
2615e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2625e3038f0Sstefano_zampini         PetscBool      same;
2635e3038f0Sstefano_zampini 
2645e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2655e3038f0Sstefano_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);
2665e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2675e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2685e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2695e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2705e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2715e3038f0Sstefano_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);
2725e3038f0Sstefano_zampini       }
2735e3038f0Sstefano_zampini     }
2745e3038f0Sstefano_zampini   }
2755e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
2765e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
2775e3038f0Sstefano_zampini     rl2g = NULL;
2785e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
2795e3038f0Sstefano_zampini       PetscInt n1,n2;
2805e3038f0Sstefano_zampini 
2815e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
2829e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
2839e7b2b25Sstefano_zampini         Mat T;
2849e7b2b25Sstefano_zampini 
2859e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
2869e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
2879e7b2b25Sstefano_zampini       } else {
2885e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
2899e7b2b25Sstefano_zampini       }
2905e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2915e3038f0Sstefano_zampini       if (!n1) continue;
2925e3038f0Sstefano_zampini       if (!rl2g) {
2935e3038f0Sstefano_zampini         rl2g = cl2g;
2945e3038f0Sstefano_zampini       } else {
2955e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2965e3038f0Sstefano_zampini         PetscBool      same;
2975e3038f0Sstefano_zampini 
2985e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2995e3038f0Sstefano_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);
3005e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
3015e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
3025e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
3035e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
3045e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
3055e3038f0Sstefano_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);
3065e3038f0Sstefano_zampini       }
3075e3038f0Sstefano_zampini     }
3085e3038f0Sstefano_zampini   }
3095e3038f0Sstefano_zampini #endif
3105e3038f0Sstefano_zampini 
3115e3038f0Sstefano_zampini   B = NULL;
3125e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
3135b003df0Sstefano_zampini     PetscInt stl;
3145b003df0Sstefano_zampini 
3155e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
3165e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
3175e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3185b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
3195e3038f0Sstefano_zampini       Mat            usedmat;
3205e3038f0Sstefano_zampini       Mat_IS         *matis;
3215e3038f0Sstefano_zampini       const PetscInt *idxs;
3225e3038f0Sstefano_zampini 
3235e3038f0Sstefano_zampini       /* local IS for local NEST */
3245b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
3255e3038f0Sstefano_zampini 
3265e3038f0Sstefano_zampini       /* l2gmap */
3275e3038f0Sstefano_zampini       j = 0;
3285e3038f0Sstefano_zampini       usedmat = nest[i][j];
3299e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
3309e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
3319e7b2b25Sstefano_zampini 
3329e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3339e7b2b25Sstefano_zampini         Mat T;
3349e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3359e7b2b25Sstefano_zampini         usedmat = T;
3369e7b2b25Sstefano_zampini       }
33782d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3385e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3395e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
3409e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3419e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3429e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3439e7b2b25Sstefano_zampini       } else {
3445e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3455e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3469e7b2b25Sstefano_zampini       }
3475e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
3485e3038f0Sstefano_zampini       stl += lr[i];
3495e3038f0Sstefano_zampini     }
3505e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
3515e3038f0Sstefano_zampini 
3525e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
3535e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
3545e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3555b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
3565e3038f0Sstefano_zampini       Mat            usedmat;
3575e3038f0Sstefano_zampini       Mat_IS         *matis;
3585e3038f0Sstefano_zampini       const PetscInt *idxs;
3595e3038f0Sstefano_zampini 
3605e3038f0Sstefano_zampini       /* local IS for local NEST */
3615b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
3625e3038f0Sstefano_zampini 
3635e3038f0Sstefano_zampini       /* l2gmap */
3645e3038f0Sstefano_zampini       j = 0;
3655e3038f0Sstefano_zampini       usedmat = nest[j][i];
3669e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
3679e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
3689e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3699e7b2b25Sstefano_zampini         Mat T;
3709e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3719e7b2b25Sstefano_zampini         usedmat = T;
3729e7b2b25Sstefano_zampini       }
37382d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3745e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3755e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
3769e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3779e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3789e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3799e7b2b25Sstefano_zampini       } else {
3805e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3815e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3829e7b2b25Sstefano_zampini       }
3835e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
3845e3038f0Sstefano_zampini       stl += lc[i];
3855e3038f0Sstefano_zampini     }
3865e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
3875e3038f0Sstefano_zampini 
3885e3038f0Sstefano_zampini     /* Create MATIS */
3895e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
3905e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
3915e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
3925e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
3935e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
3945e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
3955e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3965e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3975e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
3989e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
3999e7b2b25Sstefano_zampini       if (istrans[i]) {
4009e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
4019e7b2b25Sstefano_zampini       }
4029e7b2b25Sstefano_zampini     }
4035e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
4045e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
4055e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4065e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4075e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
4085e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
4095e3038f0Sstefano_zampini     } else {
4105e3038f0Sstefano_zampini       *newmat = B;
4115e3038f0Sstefano_zampini     }
4125e3038f0Sstefano_zampini   } else {
4135e3038f0Sstefano_zampini     if (lreuse) {
4145e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4155e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
4165e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
4175e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
4185e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
4199e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
4209e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
4219e7b2b25Sstefano_zampini             }
4225e3038f0Sstefano_zampini           }
4235e3038f0Sstefano_zampini         }
4245e3038f0Sstefano_zampini       }
4255e3038f0Sstefano_zampini     } else {
4265b003df0Sstefano_zampini       PetscInt stl;
4275b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
4285b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
4295b003df0Sstefano_zampini         stl  += lr[i];
4305e3038f0Sstefano_zampini       }
4315b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
4325b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
4335b003df0Sstefano_zampini         stl  += lc[i];
4345e3038f0Sstefano_zampini       }
4355e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
4369e7b2b25Sstefano_zampini       if (istrans[i]) {
4379e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
4389e7b2b25Sstefano_zampini       }
4395e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
4405e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
4415e3038f0Sstefano_zampini     }
4425e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4435e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4445e3038f0Sstefano_zampini   }
4455e3038f0Sstefano_zampini 
4465b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
4475b003df0Sstefano_zampini   convert = PETSC_FALSE;
4485b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
4495b003df0Sstefano_zampini   if (convert) {
4505b003df0Sstefano_zampini     Mat              M;
4515b003df0Sstefano_zampini     MatISLocalFields lf;
4525b003df0Sstefano_zampini     PetscContainer   c;
4535b003df0Sstefano_zampini 
4545b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4555b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
4565b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
4575b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
4585b003df0Sstefano_zampini 
4595b003df0Sstefano_zampini     /* attach local fields to the matrix */
4605b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
4615b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
4625b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
4635b003df0Sstefano_zampini       PetscInt n,st;
4645b003df0Sstefano_zampini 
4655b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
4665b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
4675b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
4685b003df0Sstefano_zampini     }
4695b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
4705b003df0Sstefano_zampini       PetscInt n,st;
4715b003df0Sstefano_zampini 
4725b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
4735b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
4745b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
4755b003df0Sstefano_zampini     }
4765b003df0Sstefano_zampini     lf->nr = nr;
4775b003df0Sstefano_zampini     lf->nc = nc;
4785b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
4795b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
4805b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
4815b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
4825b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
4835b003df0Sstefano_zampini   }
4845b003df0Sstefano_zampini 
4855e3038f0Sstefano_zampini   /* Free workspace */
4865e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4875e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
4885e3038f0Sstefano_zampini   }
4895e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
4905e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
4915e3038f0Sstefano_zampini   }
4929e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
4935b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
4945e3038f0Sstefano_zampini   PetscFunctionReturn(0);
4955e3038f0Sstefano_zampini }
4965e3038f0Sstefano_zampini 
497ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
498ad219c80Sstefano_zampini {
499ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
500ad219c80Sstefano_zampini   Vec               ll,rr;
501ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
502ad219c80Sstefano_zampini   PetscScalar       *x,*y;
503ad219c80Sstefano_zampini   PetscErrorCode    ierr;
504ad219c80Sstefano_zampini 
505ad219c80Sstefano_zampini   PetscFunctionBegin;
506ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
507ad219c80Sstefano_zampini   if (l) {
508ad219c80Sstefano_zampini     ll   = matis->y;
509ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
510ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
511ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
512ad219c80Sstefano_zampini   } else {
513ad219c80Sstefano_zampini     ll = NULL;
514ad219c80Sstefano_zampini   }
515ad219c80Sstefano_zampini   if (r) {
516ad219c80Sstefano_zampini     rr   = matis->x;
517ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
518ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
519ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
520ad219c80Sstefano_zampini   } else {
521ad219c80Sstefano_zampini     rr = NULL;
522ad219c80Sstefano_zampini   }
523ad219c80Sstefano_zampini   if (ll) {
524ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
525ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
526ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
527ad219c80Sstefano_zampini   }
528ad219c80Sstefano_zampini   if (rr) {
529ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
530ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
531ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
532ad219c80Sstefano_zampini   }
533ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
534ad219c80Sstefano_zampini   PetscFunctionReturn(0);
535ad219c80Sstefano_zampini }
536ad219c80Sstefano_zampini 
5377fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
5387fa8f2d3SStefano Zampini {
5397fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
5407fa8f2d3SStefano Zampini   MatInfo        info;
5417fa8f2d3SStefano Zampini   PetscReal      isend[6],irecv[6];
5427fa8f2d3SStefano Zampini   PetscInt       bs;
5437fa8f2d3SStefano Zampini   PetscErrorCode ierr;
5447fa8f2d3SStefano Zampini 
5457fa8f2d3SStefano Zampini   PetscFunctionBegin;
5467fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
5477fa8f2d3SStefano Zampini   if (matis->A->ops->getinfo) {
5487fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
5497fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
5507fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
5517fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
5527fa8f2d3SStefano Zampini     isend[3] = info.memory;
5537fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
5547fa8f2d3SStefano Zampini   } else {
5557fa8f2d3SStefano Zampini     isend[0] = 0.;
5567fa8f2d3SStefano Zampini     isend[1] = 0.;
5577fa8f2d3SStefano Zampini     isend[2] = 0.;
5587fa8f2d3SStefano Zampini     isend[3] = 0.;
5597fa8f2d3SStefano Zampini     isend[4] = 0.;
5607fa8f2d3SStefano Zampini   }
5617fa8f2d3SStefano Zampini   isend[5] = matis->A->num_ass;
5627fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
5637fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
5647fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
5657fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
5667fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
5677fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
5687fa8f2d3SStefano Zampini     ginfo->assemblies   = isend[5];
5697fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
5707fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
5717fa8f2d3SStefano Zampini 
5727fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
5737fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
5747fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
5757fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
5767fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
5777fa8f2d3SStefano Zampini     ginfo->assemblies   = irecv[5];
5787fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
5797fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
5807fa8f2d3SStefano Zampini 
5817fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
5827fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
5837fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
5847fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
5857fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
5867fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
587d7f69cd0SStefano Zampini   }
588d7f69cd0SStefano Zampini   ginfo->block_size        = bs;
589d7f69cd0SStefano Zampini   ginfo->fill_ratio_given  = 0;
590d7f69cd0SStefano Zampini   ginfo->fill_ratio_needed = 0;
591d7f69cd0SStefano Zampini   ginfo->factor_mallocs    = 0;
5925e3038f0Sstefano_zampini   PetscFunctionReturn(0);
5935e3038f0Sstefano_zampini }
5945e3038f0Sstefano_zampini 
595d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
596d7f69cd0SStefano Zampini {
597d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
598d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
599d7f69cd0SStefano Zampini 
600d7f69cd0SStefano Zampini   PetscFunctionBegin;
601cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
602cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
603d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
604d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
605d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
606d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
607d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
608d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
609cf37664fSBarry Smith   } else {
610cf37664fSBarry Smith     C = *B;
611d7f69cd0SStefano Zampini   }
612d7f69cd0SStefano Zampini 
613d7f69cd0SStefano Zampini   /* perform local transposition */
614d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
615d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
616d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
617d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
618d7f69cd0SStefano Zampini 
619cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
620d7f69cd0SStefano Zampini     *B = C;
621d7f69cd0SStefano Zampini   } else {
622d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
623d7f69cd0SStefano Zampini   }
6247aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6257aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
626d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
627d7f69cd0SStefano Zampini }
628d7f69cd0SStefano Zampini 
6293fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
6303fd1c9e7SStefano Zampini {
6313fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
6323fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6333fd1c9e7SStefano Zampini 
6343fd1c9e7SStefano Zampini   PetscFunctionBegin;
6353fd1c9e7SStefano Zampini   if (!D) { /* this code branch is used by MatShift_IS */
6363fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
6373fd1c9e7SStefano Zampini   } else {
6383fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6393fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6403fd1c9e7SStefano Zampini   }
6413fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
6423fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
6433fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6443fd1c9e7SStefano Zampini }
6453fd1c9e7SStefano Zampini 
6463fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
6473fd1c9e7SStefano Zampini {
6483fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6493fd1c9e7SStefano Zampini 
6503fd1c9e7SStefano Zampini   PetscFunctionBegin;
6513fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
6523fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6533fd1c9e7SStefano Zampini }
6543fd1c9e7SStefano Zampini 
655f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
656f26d0771SStefano Zampini {
657f26d0771SStefano Zampini   PetscErrorCode ierr;
658f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
659f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
660f26d0771SStefano Zampini 
661f26d0771SStefano Zampini   PetscFunctionBegin;
662f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
663f26d0771SStefano 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);
664f26d0771SStefano Zampini #endif
665f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
666f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
667f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
668f26d0771SStefano Zampini   PetscFunctionReturn(0);
669f26d0771SStefano Zampini }
670f26d0771SStefano Zampini 
671f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
672f26d0771SStefano Zampini {
673f26d0771SStefano Zampini   PetscErrorCode ierr;
674f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
675f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
676f26d0771SStefano Zampini 
677f26d0771SStefano Zampini   PetscFunctionBegin;
678f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
679f26d0771SStefano 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);
680f26d0771SStefano Zampini #endif
681f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
682f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
683f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
684f26d0771SStefano Zampini   PetscFunctionReturn(0);
685f26d0771SStefano Zampini }
686f26d0771SStefano Zampini 
687f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
688a8116848SStefano Zampini {
689a8116848SStefano Zampini   PetscInt      *owners = map->range;
690a8116848SStefano Zampini   PetscInt       n      = map->n;
691a8116848SStefano Zampini   PetscSF        sf;
692a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
693a8116848SStefano Zampini   PetscSFNode   *ridxs;
694a8116848SStefano Zampini   PetscMPIInt    rank;
695a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
696a8116848SStefano Zampini   PetscErrorCode ierr;
697a8116848SStefano Zampini 
698a8116848SStefano Zampini   PetscFunctionBegin;
699fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
700a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
701a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
702a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
703a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
704a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
705a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
706a8116848SStefano Zampini     const PetscInt idx = idxs[r];
707a8116848SStefano 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);
708a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
709a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
710a8116848SStefano Zampini     }
711a8116848SStefano Zampini     ridxs[r].rank = p;
712a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
713a8116848SStefano Zampini   }
714a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
715a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
716a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
717a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
718f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
719a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
720f0ae7da4SStefano Zampini 
721f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
722a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
723a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
724a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
725a8116848SStefano Zampini     start -= cum;
726a8116848SStefano Zampini     cum = 0;
727a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
728a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
729a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
730a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
731a8116848SStefano Zampini   }
732a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
733a8116848SStefano Zampini   /* Compress and put in indices */
734a8116848SStefano Zampini   for (r = 0; r < n; ++r)
735a8116848SStefano Zampini     if (lidxs[r] >= 0) {
736a8116848SStefano Zampini       if (work) work[len] = work[r];
737a8116848SStefano Zampini       lidxs[len++] = r;
738a8116848SStefano Zampini     }
739a8116848SStefano Zampini   if (on) *on = len;
740a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
741a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
742a8116848SStefano Zampini   PetscFunctionReturn(0);
743a8116848SStefano Zampini }
744a8116848SStefano Zampini 
7457dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
746a8116848SStefano Zampini {
747a8116848SStefano Zampini   Mat               locmat,newlocmat;
748a8116848SStefano Zampini   Mat_IS            *newmatis;
749a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
750a8116848SStefano Zampini   Vec               rtest,ltest;
751a8116848SStefano Zampini   const PetscScalar *array;
752a8116848SStefano Zampini #endif
753a8116848SStefano Zampini   const PetscInt    *idxs;
754a8116848SStefano Zampini   PetscInt          i,m,n;
755a8116848SStefano Zampini   PetscErrorCode    ierr;
756a8116848SStefano Zampini 
757a8116848SStefano Zampini   PetscFunctionBegin;
758a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
759a8116848SStefano Zampini     PetscBool ismatis;
760a8116848SStefano Zampini 
761a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
762a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
763a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
764a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
765a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
766a8116848SStefano Zampini   }
767a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
768a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
769a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
770a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
771a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
772a8116848SStefano Zampini   for (i=0;i<n;i++) {
773a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
774a8116848SStefano Zampini   }
775a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
776a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
777a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
778a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
779a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
780fd479f66SMatthew 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]));
781a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
782a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
783a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
784a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
785a8116848SStefano Zampini   for (i=0;i<n;i++) {
786a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
787a8116848SStefano Zampini   }
788a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
789a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
790a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
791a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
792a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
793fd479f66SMatthew 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]));
794a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
795a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
796a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
797a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
798a8116848SStefano Zampini #endif
799a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
800a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
801a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
802a8116848SStefano Zampini     IS                     is;
803a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
8046dd40735SStefano Zampini     PetscInt               ll,newloc;
805a8116848SStefano Zampini     MPI_Comm               comm;
806a8116848SStefano Zampini 
807a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
808a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
809a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
810a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
811a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
812a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
813a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
814a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
815f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
816a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
8173d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
8183d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
819a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
820a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
821a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
822a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
823a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
8243d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
825a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
826a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8273d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
828a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
829a8116848SStefano Zampini         lidxs[newloc] = i;
830a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
831a8116848SStefano Zampini       }
832a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
833a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
834a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
835a8116848SStefano Zampini     /* local is to extract local submatrix */
836a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
837a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
838a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
839a8116848SStefano Zampini       PetscBool cong;
840a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
841a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
842a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
843a8116848SStefano Zampini     }
844a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
845a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
846a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
847a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
848a8116848SStefano Zampini     } else {
849a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
850a8116848SStefano Zampini 
851a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
852a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
853f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
854a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
8553d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
856a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
857a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
858a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
859a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
860a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
8613d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
862a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
863a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8643d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
865a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
866a8116848SStefano Zampini           lidxs[newloc] = i;
867a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
868a8116848SStefano Zampini         }
869a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
870a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
871a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
872a8116848SStefano Zampini       /* local is to extract local submatrix */
873a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
874a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
875a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
876a8116848SStefano Zampini     }
877a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
878a8116848SStefano Zampini   } else {
879a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
880a8116848SStefano Zampini   }
881a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
882a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
8837dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
884a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
885a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
886a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
887a8116848SStefano Zampini   }
888a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
889a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
890a8116848SStefano Zampini   PetscFunctionReturn(0);
891a8116848SStefano Zampini }
892a8116848SStefano Zampini 
893a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
8942b404112SStefano Zampini {
8952b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
8962b404112SStefano Zampini   PetscBool      ismatis;
8972b404112SStefano Zampini   PetscErrorCode ierr;
8982b404112SStefano Zampini 
8992b404112SStefano Zampini   PetscFunctionBegin;
9002b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
9012b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
9022b404112SStefano Zampini   b = (Mat_IS*)B->data;
9032b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
9042b404112SStefano Zampini   PetscFunctionReturn(0);
9052b404112SStefano Zampini }
9062b404112SStefano Zampini 
907a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
9086bd84002SStefano Zampini {
909527b2640SStefano Zampini   Vec               v;
910527b2640SStefano Zampini   const PetscScalar *array;
911527b2640SStefano Zampini   PetscInt          i,n;
9126bd84002SStefano Zampini   PetscErrorCode    ierr;
9136bd84002SStefano Zampini 
9146bd84002SStefano Zampini   PetscFunctionBegin;
915527b2640SStefano Zampini   *missing = PETSC_FALSE;
916527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
917527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
918527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
919527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
920527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
921527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
922527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
923527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
924527b2640SStefano Zampini   if (d) {
925527b2640SStefano Zampini     *d = -1;
926527b2640SStefano Zampini     if (*missing) {
927527b2640SStefano Zampini       PetscInt rstart;
928527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
929527b2640SStefano Zampini       *d = i+rstart;
930527b2640SStefano Zampini     }
931527b2640SStefano Zampini   }
9326bd84002SStefano Zampini   PetscFunctionReturn(0);
9336bd84002SStefano Zampini }
9346bd84002SStefano Zampini 
935cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
93628f4e0baSStefano Zampini {
93728f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
93828f4e0baSStefano Zampini   const PetscInt *gidxs;
9394f2d7cafSStefano Zampini   PetscInt       nleaves;
94028f4e0baSStefano Zampini   PetscErrorCode ierr;
94128f4e0baSStefano Zampini 
94228f4e0baSStefano Zampini   PetscFunctionBegin;
9434f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
94428f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
9453bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9464f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
9474f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
9483bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9494f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
950a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
9513d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
952a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
953a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9543d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
955a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9563d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
957a8116848SStefano Zampini   } else {
958a8116848SStefano Zampini     matis->csf = matis->sf;
959a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
960a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
961a8116848SStefano Zampini   }
96228f4e0baSStefano Zampini   PetscFunctionReturn(0);
96328f4e0baSStefano Zampini }
9642e1947a5SStefano Zampini 
965eb82efa4SStefano Zampini /*@
966a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
967a88811baSStefano Zampini 
968a88811baSStefano Zampini    Collective on MPI_Comm
969a88811baSStefano Zampini 
970a88811baSStefano Zampini    Input Parameters:
971a88811baSStefano Zampini +  B - the matrix
972a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
973a88811baSStefano Zampini            (same value is used for all local rows)
974a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
975a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
976a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
977a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
978a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
979a88811baSStefano Zampini            the diagonal entry even if it is zero.
980a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
981a88811baSStefano Zampini            submatrix (same value is used for all local rows).
982a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
983a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
984a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
985a88811baSStefano Zampini            structure. The size of this array is equal to the number
986a88811baSStefano Zampini            of local rows, i.e 'm'.
987a88811baSStefano Zampini 
988a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
989a88811baSStefano Zampini 
990a88811baSStefano Zampini    Level: intermediate
991a88811baSStefano Zampini 
992a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
993a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
994a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
995a88811baSStefano Zampini 
996a88811baSStefano Zampini .keywords: matrix
997a88811baSStefano Zampini 
9983c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
999a88811baSStefano Zampini @*/
10002e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10012e1947a5SStefano Zampini {
10022e1947a5SStefano Zampini   PetscErrorCode ierr;
10032e1947a5SStefano Zampini 
10042e1947a5SStefano Zampini   PetscFunctionBegin;
10052e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
10062e1947a5SStefano Zampini   PetscValidType(B,1);
10072e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
10082e1947a5SStefano Zampini   PetscFunctionReturn(0);
10092e1947a5SStefano Zampini }
10102e1947a5SStefano Zampini 
10117230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10122e1947a5SStefano Zampini {
10132e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
101428f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
10152e1947a5SStefano Zampini   PetscErrorCode ierr;
10162e1947a5SStefano Zampini 
10172e1947a5SStefano Zampini   PetscFunctionBegin;
10186c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1019cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
10204f2d7cafSStefano Zampini 
10214f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
10224f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
10234f2d7cafSStefano Zampini 
10244f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
10254f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
10264f2d7cafSStefano Zampini 
102728f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
102828f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
102928f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
103028f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
10314f2d7cafSStefano Zampini 
10324f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
103328f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
1034*0f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
1035*0f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
1036*0f2f62c7SStefano Zampini #endif
10374f2d7cafSStefano Zampini 
10384f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
103928f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10404f2d7cafSStefano Zampini 
10414f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
104228f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
1043*0f2f62c7SStefano Zampini 
1044*0f2f62c7SStefano Zampini   /* for other matrix types */
1045*0f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
10462e1947a5SStefano Zampini   PetscFunctionReturn(0);
10472e1947a5SStefano Zampini }
1048b4319ba4SBarry Smith 
10493927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
10503927de2eSStefano Zampini {
10513927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
10523927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1053ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
10543927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
10553927de2eSStefano Zampini   PetscInt        lrows,lcols;
10563927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
10573927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
10583927de2eSStefano Zampini   PetscBool       isdense,issbaij;
10593927de2eSStefano Zampini   PetscErrorCode  ierr;
10603927de2eSStefano Zampini 
10613927de2eSStefano Zampini   PetscFunctionBegin;
10623927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
10633927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
10643927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
10653927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
10663927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
10673927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1068ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1069ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
10707230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1071ecf5a873SStefano Zampini   } else {
1072ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1073ecf5a873SStefano Zampini   }
1074ecf5a873SStefano Zampini 
10753927de2eSStefano Zampini   if (issbaij) {
10763927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
10773927de2eSStefano Zampini   }
10783927de2eSStefano Zampini   /*
1079ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
10803927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
10813927de2eSStefano Zampini   */
1082cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
10833927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
10843927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
10853927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
10863927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
10873927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
10883927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
10893927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
10903927de2eSStefano Zampini       row_ownership[j] = i;
10913927de2eSStefano Zampini     }
10923927de2eSStefano Zampini   }
10937230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
10943927de2eSStefano Zampini 
10953927de2eSStefano Zampini   /*
10963927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
10973927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
10983927de2eSStefano Zampini   */
10993927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
11003927de2eSStefano Zampini   /* preallocation as a MATAIJ */
11013927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
11023927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
110312dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
110412dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1105ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
11063927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11073927de2eSStefano Zampini           my_dnz[i] += 1;
11083927de2eSStefano Zampini         } else { /* offdiag block */
11093927de2eSStefano Zampini           my_onz[i] += 1;
11103927de2eSStefano Zampini         }
11113927de2eSStefano Zampini       }
11123927de2eSStefano Zampini     }
1113bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1114bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1115bb1015c3SStefano Zampini     PetscBool      done;
1116bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1117938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1118bb1015c3SStefano Zampini     jptr = jj;
1119bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1120bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1121bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1122bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1123bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1124bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1125bb1015c3SStefano Zampini           my_dnz[i] += 1;
1126bb1015c3SStefano Zampini         } else { /* offdiag block */
1127bb1015c3SStefano Zampini           my_onz[i] += 1;
1128bb1015c3SStefano Zampini         }
1129bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1130bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1131bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1132bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1133bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1134bb1015c3SStefano Zampini           } else {
1135bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1136bb1015c3SStefano Zampini           }
1137bb1015c3SStefano Zampini         }
1138bb1015c3SStefano Zampini       }
1139bb1015c3SStefano Zampini     }
1140bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1141938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1142bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
11433927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
11443927de2eSStefano Zampini       const PetscInt *cols;
1145ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
11463927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11473927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
11483927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1149ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
11503927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11513927de2eSStefano Zampini           my_dnz[i] += 1;
11523927de2eSStefano Zampini         } else { /* offdiag block */
11533927de2eSStefano Zampini           my_onz[i] += 1;
11543927de2eSStefano Zampini         }
11553927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1156d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
11573927de2eSStefano Zampini           owner = row_ownership[index_col];
11583927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1159d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
11603927de2eSStefano Zampini           } else {
1161d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
11623927de2eSStefano Zampini           }
11633927de2eSStefano Zampini         }
11643927de2eSStefano Zampini       }
11653927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11663927de2eSStefano Zampini     }
11673927de2eSStefano Zampini   }
1168ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
11697230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1170ecf5a873SStefano Zampini   }
11714f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
11723927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1173ecf5a873SStefano Zampini 
1174ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
11753927de2eSStefano Zampini   if (maxreduce) {
11763927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11773927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1178bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11793927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
11803927de2eSStefano Zampini   } else {
11813927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
11823927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1183bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
11843927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
11853927de2eSStefano Zampini   }
11863927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
11873927de2eSStefano Zampini 
11883927de2eSStefano Zampini   /* Resize preallocation if overestimated */
11893927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
11903927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
11913927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
11923927de2eSStefano Zampini   }
11931670daf9Sstefano_zampini 
11941670daf9Sstefano_zampini   /* Set preallocation */
11953927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
11963927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
11973927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
11983927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
11993927de2eSStefano Zampini   }
12003927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12013927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12023927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
12033927de2eSStefano Zampini   if (issbaij) {
12043927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
12053927de2eSStefano Zampini   }
12063927de2eSStefano Zampini   PetscFunctionReturn(0);
12073927de2eSStefano Zampini }
12083927de2eSStefano Zampini 
12097230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1210b7ce53b6SStefano Zampini {
1211b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1212d9a9e74cSStefano Zampini   Mat            local_mat;
1213b7ce53b6SStefano Zampini   /* info on mat */
12143cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1215b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1216b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1217b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1218b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1219b9ed4604SStefano Zampini #endif
12207c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1221b7ce53b6SStefano Zampini   /* values insertion */
1222b7ce53b6SStefano Zampini   PetscScalar    *array;
1223b7ce53b6SStefano Zampini   /* work */
1224b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1225b7ce53b6SStefano Zampini 
1226b7ce53b6SStefano Zampini   PetscFunctionBegin;
1227b7ce53b6SStefano Zampini   /* get info from mat */
12287c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
12297c03b4e8SStefano Zampini   if (nsubdomains == 1) {
12301670daf9Sstefano_zampini     Mat            B;
12311670daf9Sstefano_zampini     IS             rows,cols;
1232acdf38a7Sstefano_zampini     IS             irows,icols;
12331670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
12341670daf9Sstefano_zampini 
12351670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
12361670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
12371670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
12381670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
12391670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
12401670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1241acdf38a7Sstefano_zampini     ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1242acdf38a7Sstefano_zampini     ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1243acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr);
1244acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr);
1245acdf38a7Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
1246acdf38a7Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
1247acdf38a7Sstefano_zampini     ierr = MatConvert(matis->A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
12487dae84e0SHong Zhang     ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1249acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1250acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1251acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
12527c03b4e8SStefano Zampini     PetscFunctionReturn(0);
12537c03b4e8SStefano Zampini   }
1254b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1255b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
12563cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1257b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1258b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
1259686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1260b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1261b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1262b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1263b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1264b9ed4604SStefano Zampini   lb[0] = isseqdense;
1265b9ed4604SStefano Zampini   lb[1] = isseqaij;
1266b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1267b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1268b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1269b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1270b9ed4604SStefano Zampini #endif
1271b7ce53b6SStefano Zampini 
1272b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
12733927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
12743cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
12753927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
1276b9ed4604SStefano Zampini     if (!isseqsbaij) {
1277b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1278b9ed4604SStefano Zampini     } else {
1279b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1280b9ed4604SStefano Zampini     }
12813927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1282b7ce53b6SStefano Zampini   } else {
12833cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1284b7ce53b6SStefano Zampini     /* some checks */
1285b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1286b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
12873cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
12886c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
12896c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
12906c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
12916c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
12926c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1293b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1294b7ce53b6SStefano Zampini   }
1295d9a9e74cSStefano Zampini 
1296b9ed4604SStefano Zampini   if (isseqsbaij) {
1297d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1298d9a9e74cSStefano Zampini   } else {
1299d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1300d9a9e74cSStefano Zampini     local_mat = matis->A;
1301d9a9e74cSStefano Zampini   }
1302686e3a49SStefano Zampini 
1303b7ce53b6SStefano Zampini   /* Set values */
1304ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1305b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
130665066ba5SStefano Zampini     PetscInt i,*dummy;
1307ecf5a873SStefano Zampini 
130865066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
130965066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
1310b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1311d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
131265066ba5SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
1313d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
131465066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
1315686e3a49SStefano Zampini   } else if (isseqaij) {
1316ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1317686e3a49SStefano Zampini     PetscBool done;
1318686e3a49SStefano Zampini 
1319d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1320938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1321d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1322686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1323ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1324686e3a49SStefano Zampini     }
1325d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1326938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1327d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1328686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1329ecf5a873SStefano Zampini     PetscInt i;
1330c0962df8SStefano Zampini 
1331686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1332686e3a49SStefano Zampini       PetscInt       j;
1333ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1334686e3a49SStefano Zampini 
1335ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1336ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1337ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1338686e3a49SStefano Zampini     }
1339b7ce53b6SStefano Zampini   }
1340b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1341d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1342b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1343b9ed4604SStefano Zampini   if (isseqdense) {
1344b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1345b7ce53b6SStefano Zampini   }
1346b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1347b7ce53b6SStefano Zampini }
1348b7ce53b6SStefano Zampini 
1349b7ce53b6SStefano Zampini /*@
1350b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1351b7ce53b6SStefano Zampini 
1352b7ce53b6SStefano Zampini   Input Parameter:
1353b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1354b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1355b7ce53b6SStefano Zampini 
1356b7ce53b6SStefano Zampini   Output Parameter:
1357b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1358b7ce53b6SStefano Zampini 
1359b7ce53b6SStefano Zampini   Level: developer
1360b7ce53b6SStefano Zampini 
1361eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1362b7ce53b6SStefano Zampini 
1363b7ce53b6SStefano Zampini .seealso: MATIS
1364b7ce53b6SStefano Zampini @*/
1365b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1366b7ce53b6SStefano Zampini {
1367b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1368b7ce53b6SStefano Zampini 
1369b7ce53b6SStefano Zampini   PetscFunctionBegin;
1370b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1371b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1372b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1373b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1374b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1375b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
13766c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1377b7ce53b6SStefano Zampini   }
1378b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1379b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1380b7ce53b6SStefano Zampini }
1381b7ce53b6SStefano Zampini 
1382ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1383ad6194a2SStefano Zampini {
1384ad6194a2SStefano Zampini   PetscErrorCode ierr;
1385ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1386ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1387ad6194a2SStefano Zampini   Mat            B,localmat;
1388ad6194a2SStefano Zampini 
1389ad6194a2SStefano Zampini   PetscFunctionBegin;
1390ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1391ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1392ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1393e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1394ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1395ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1396b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1397ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1398ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1399ad6194a2SStefano Zampini   *newmat = B;
1400ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1401ad6194a2SStefano Zampini }
1402ad6194a2SStefano Zampini 
1403a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
140469796d55SStefano Zampini {
140569796d55SStefano Zampini   PetscErrorCode ierr;
140669796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
140769796d55SStefano Zampini   PetscBool      local_sym;
140869796d55SStefano Zampini 
140969796d55SStefano Zampini   PetscFunctionBegin;
141069796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1411b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
141269796d55SStefano Zampini   PetscFunctionReturn(0);
141369796d55SStefano Zampini }
141469796d55SStefano Zampini 
1415a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
141669796d55SStefano Zampini {
141769796d55SStefano Zampini   PetscErrorCode ierr;
141869796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
141969796d55SStefano Zampini   PetscBool      local_sym;
142069796d55SStefano Zampini 
142169796d55SStefano Zampini   PetscFunctionBegin;
142269796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1423b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
142469796d55SStefano Zampini   PetscFunctionReturn(0);
142569796d55SStefano Zampini }
142669796d55SStefano Zampini 
142745471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
142845471136SStefano Zampini {
142945471136SStefano Zampini   PetscErrorCode ierr;
143045471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
143145471136SStefano Zampini   PetscBool      local_sym;
143245471136SStefano Zampini 
143345471136SStefano Zampini   PetscFunctionBegin;
143445471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
143545471136SStefano Zampini     *flg = PETSC_FALSE;
143645471136SStefano Zampini     PetscFunctionReturn(0);
143745471136SStefano Zampini   }
143845471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
143945471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
144045471136SStefano Zampini   PetscFunctionReturn(0);
144145471136SStefano Zampini }
144245471136SStefano Zampini 
1443a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1444b4319ba4SBarry Smith {
1445dfbe8321SBarry Smith   PetscErrorCode ierr;
1446b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1447b4319ba4SBarry Smith 
1448b4319ba4SBarry Smith   PetscFunctionBegin;
14496bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1450e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1451e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
14526bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
14536bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
14543fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1455a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1456a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1457a8116848SStefano Zampini   if (b->sf != b->csf) {
1458a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1459a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1460a8116848SStefano Zampini   }
146128f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
146228f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1463bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1464dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1465bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1466b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1467b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
14682e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1469cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1470b4319ba4SBarry Smith   PetscFunctionReturn(0);
1471b4319ba4SBarry Smith }
1472b4319ba4SBarry Smith 
1473a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1474b4319ba4SBarry Smith {
1475dfbe8321SBarry Smith   PetscErrorCode ierr;
1476b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1477b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1478b4319ba4SBarry Smith 
1479b4319ba4SBarry Smith   PetscFunctionBegin;
1480b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1481e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1482e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1483b4319ba4SBarry Smith 
1484b4319ba4SBarry Smith   /* multiply the local matrix */
1485b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1486b4319ba4SBarry Smith 
1487b4319ba4SBarry Smith   /* scatter product back into global memory */
14882dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1489e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1490e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1491b4319ba4SBarry Smith   PetscFunctionReturn(0);
1492b4319ba4SBarry Smith }
1493b4319ba4SBarry Smith 
1494a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
14952e74eeadSLisandro Dalcin {
1496650997f4SStefano Zampini   Vec            temp_vec;
14972e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14982e74eeadSLisandro Dalcin 
14992e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1500650997f4SStefano Zampini   if (v3 != v2) {
1501650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1502650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1503650997f4SStefano Zampini   } else {
1504650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1505650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1506650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1507650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1508650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1509650997f4SStefano Zampini   }
15102e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15112e74eeadSLisandro Dalcin }
15122e74eeadSLisandro Dalcin 
1513a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
15142e74eeadSLisandro Dalcin {
15152e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
15162e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15172e74eeadSLisandro Dalcin 
1518e176bc59SStefano Zampini   PetscFunctionBegin;
15192e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1520e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1521e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15222e74eeadSLisandro Dalcin 
15232e74eeadSLisandro Dalcin   /* multiply the local matrix */
1524e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
15252e74eeadSLisandro Dalcin 
15262e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1527e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1528e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1529e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15302e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15312e74eeadSLisandro Dalcin }
15322e74eeadSLisandro Dalcin 
1533a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15342e74eeadSLisandro Dalcin {
1535650997f4SStefano Zampini   Vec            temp_vec;
15362e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15372e74eeadSLisandro Dalcin 
15382e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1539650997f4SStefano Zampini   if (v3 != v2) {
1540650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1541650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1542650997f4SStefano Zampini   } else {
1543650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1544650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1545650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1546650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1547650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1548650997f4SStefano Zampini   }
15492e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15502e74eeadSLisandro Dalcin }
15512e74eeadSLisandro Dalcin 
1552a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1553b4319ba4SBarry Smith {
1554b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1555dfbe8321SBarry Smith   PetscErrorCode ierr;
1556b4319ba4SBarry Smith   PetscViewer    sviewer;
1557ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1558b4319ba4SBarry Smith 
1559b4319ba4SBarry Smith   PetscFunctionBegin;
1560ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1561ee2491ecSStefano Zampini   if (isascii)  {
1562ee2491ecSStefano Zampini     PetscViewerFormat format;
1563ee2491ecSStefano Zampini 
1564ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1565ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1566ee2491ecSStefano Zampini   }
1567ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
15683f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1569b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
15703f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
15716e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1572b4319ba4SBarry Smith   PetscFunctionReturn(0);
1573b4319ba4SBarry Smith }
1574b4319ba4SBarry Smith 
1575a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1576b4319ba4SBarry Smith {
1577dfbe8321SBarry Smith   PetscErrorCode ierr;
1578e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1579b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1580b4319ba4SBarry Smith   IS             from,to;
1581e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1582b4319ba4SBarry Smith 
1583b4319ba4SBarry Smith   PetscFunctionBegin;
1584784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1585e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
15863bbff08aSStefano Zampini   /* Destroy any previous data */
158770cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
158870cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
15893fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1590e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1591e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
15921c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
1593872cf891SStefano Zampini   if (is->csf != is->sf) {
1594872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
1595872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
1596872cf891SStefano Zampini   }
159728f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
159828f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
15993bbff08aSStefano Zampini 
16003bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1601fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1602fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1603fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1604fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1605b4319ba4SBarry Smith 
1606b4319ba4SBarry Smith   /* Create the local matrix A */
1607e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1608e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1609e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1610e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1611f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1612e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1613e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1614e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1615ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1616ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1617b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1618b4319ba4SBarry Smith 
1619f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1620b4319ba4SBarry Smith     /* Create the local work vectors */
16213bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1622b4319ba4SBarry Smith 
1623e176bc59SStefano Zampini     /* setup the global to local scatters */
1624e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1625e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1626784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1627e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1628e176bc59SStefano Zampini     if (rmapping != cmapping) {
1629e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1630e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1631e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1632e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1633e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1634e176bc59SStefano Zampini     } else {
1635e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1636e176bc59SStefano Zampini       is->cctx = is->rctx;
1637e176bc59SStefano Zampini     }
16383fd1c9e7SStefano Zampini 
16393fd1c9e7SStefano Zampini     /* interface counter vector (local) */
16403fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
16413fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
16423fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16433fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16443fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16453fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16463fd1c9e7SStefano Zampini 
16473fd1c9e7SStefano Zampini     /* free workspace */
1648e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1649e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
16506bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
16516bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1652f26d0771SStefano Zampini   }
165348ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1654b4319ba4SBarry Smith   PetscFunctionReturn(0);
1655b4319ba4SBarry Smith }
1656b4319ba4SBarry Smith 
1657a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
16582e74eeadSLisandro Dalcin {
16592e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
16602e74eeadSLisandro Dalcin   PetscErrorCode ierr;
166197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
166297563a80SStefano Zampini   PetscInt       i,zm,zn;
166397563a80SStefano Zampini #endif
1664f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
16652e74eeadSLisandro Dalcin 
16662e74eeadSLisandro Dalcin   PetscFunctionBegin;
16672e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1668f26d0771SStefano 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);
166997563a80SStefano Zampini   /* count negative indices */
167097563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
167197563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
16722e74eeadSLisandro Dalcin #endif
167397563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
167497563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
167597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
167697563a80SStefano Zampini   /* count negative indices (should be the same as before) */
167797563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
167897563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
1679872cf891SStefano Zampini   /* disable check when usesetlocal is true */
1680872cf891SStefano Zampini   if (!is->usesetlocal && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
1681872cf891SStefano Zampini   if (!is->usesetlocal && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
168297563a80SStefano Zampini #endif
1683872cf891SStefano Zampini   if (is->usesetlocal) {
1684872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1685872cf891SStefano Zampini   } else {
16862e74eeadSLisandro Dalcin     ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1687872cf891SStefano Zampini   }
16882e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
16892e74eeadSLisandro Dalcin }
16902e74eeadSLisandro Dalcin 
1691a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
169297563a80SStefano Zampini {
169397563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
169497563a80SStefano Zampini   PetscErrorCode ierr;
169597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
169697563a80SStefano Zampini   PetscInt       i,zm,zn;
169797563a80SStefano Zampini #endif
1698f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
169997563a80SStefano Zampini 
170097563a80SStefano Zampini   PetscFunctionBegin;
170197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1702f26d0771SStefano 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);
170397563a80SStefano Zampini   /* count negative indices */
170497563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
170597563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
170697563a80SStefano Zampini #endif
170797563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
170897563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
170997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
171097563a80SStefano Zampini   /* count negative indices (should be the same as before) */
171197563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
171297563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
171397563a80SStefano Zampini   if (zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
171497563a80SStefano Zampini   if (zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
171597563a80SStefano Zampini #endif
171697563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
171797563a80SStefano Zampini   PetscFunctionReturn(0);
171897563a80SStefano Zampini }
171997563a80SStefano Zampini 
1720a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1721b4319ba4SBarry Smith {
1722dfbe8321SBarry Smith   PetscErrorCode ierr;
1723b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1724b4319ba4SBarry Smith 
1725b4319ba4SBarry Smith   PetscFunctionBegin;
1726872cf891SStefano Zampini   if (is->usesetlocal) {
1727872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1728872cf891SStefano Zampini   } else {
1729b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1730872cf891SStefano Zampini   }
1731b4319ba4SBarry Smith   PetscFunctionReturn(0);
1732b4319ba4SBarry Smith }
1733b4319ba4SBarry Smith 
1734a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1735f0006bf2SLisandro Dalcin {
1736f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1737f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1738f0006bf2SLisandro Dalcin 
1739f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1740f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1741f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1742f0006bf2SLisandro Dalcin }
1743f0006bf2SLisandro Dalcin 
1744f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1745f0ae7da4SStefano Zampini {
1746f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1747f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1748f0ae7da4SStefano Zampini 
1749f0ae7da4SStefano Zampini   PetscFunctionBegin;
1750f0ae7da4SStefano Zampini   if (!n) {
1751f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1752f0ae7da4SStefano Zampini   } else {
1753f0ae7da4SStefano Zampini     PetscInt i;
1754f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1755f0ae7da4SStefano Zampini 
1756f0ae7da4SStefano Zampini     if (columns) {
1757f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1758f0ae7da4SStefano Zampini     } else {
1759f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1760f0ae7da4SStefano Zampini     }
1761f0ae7da4SStefano Zampini     if (diag != 0.) {
1762f0ae7da4SStefano Zampini       const PetscScalar *array;
1763f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1764f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1765f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1766f0ae7da4SStefano Zampini       }
1767f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1768f0ae7da4SStefano Zampini     }
1769f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1770f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1771f0ae7da4SStefano Zampini   }
1772f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1773f0ae7da4SStefano Zampini }
1774f0ae7da4SStefano Zampini 
1775f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
17762e74eeadSLisandro Dalcin {
17776e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
17786e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
17796e520ac8SStefano Zampini   PetscInt       *lrows;
17802e74eeadSLisandro Dalcin   PetscErrorCode ierr;
17812e74eeadSLisandro Dalcin 
17822e74eeadSLisandro Dalcin   PetscFunctionBegin;
1783f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1784f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1785f0ae7da4SStefano Zampini     PetscBool cong;
1786f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1787f0ae7da4SStefano Zampini     if (!cong && columns) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Columns can be zeroed if and only if A->rmap and A->cmap are congruent for MATIS");
1788f0ae7da4SStefano Zampini     if (!cong && diag != 0.) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Nonzero diagonal value supported if and only if A->rmap and A->cmap are congruent for MATIS");
1789f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1790f0ae7da4SStefano Zampini   }
1791f0ae7da4SStefano Zampini #endif
17926e520ac8SStefano Zampini   /* get locally owned rows */
1793f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
17946e520ac8SStefano Zampini   /* fix right hand side if needed */
17956e520ac8SStefano Zampini   if (x && b) {
17966e520ac8SStefano Zampini     const PetscScalar *xx;
17976e520ac8SStefano Zampini     PetscScalar       *bb;
17986e520ac8SStefano Zampini 
17996e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
18006e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
18016e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
18026e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
18036e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
18042e74eeadSLisandro Dalcin   }
18056e520ac8SStefano Zampini   /* get rows associated to the local matrices */
18063d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
18076e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
18086e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
18096e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
18106e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
18116e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18126e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18136e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18146e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
18156e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1816f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
18176e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18182e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18192e74eeadSLisandro Dalcin }
18202e74eeadSLisandro Dalcin 
1821f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1822b4319ba4SBarry Smith {
1823dfbe8321SBarry Smith   PetscErrorCode ierr;
1824b4319ba4SBarry Smith 
1825b4319ba4SBarry Smith   PetscFunctionBegin;
1826f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1827f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1828f0ae7da4SStefano Zampini }
18292205254eSKarl Rupp 
1830f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1831f0ae7da4SStefano Zampini {
1832f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1833f0ae7da4SStefano Zampini 
1834f0ae7da4SStefano Zampini   PetscFunctionBegin;
1835f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1836b4319ba4SBarry Smith   PetscFunctionReturn(0);
1837b4319ba4SBarry Smith }
1838b4319ba4SBarry Smith 
1839a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1840b4319ba4SBarry Smith {
1841b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1842dfbe8321SBarry Smith   PetscErrorCode ierr;
1843b4319ba4SBarry Smith 
1844b4319ba4SBarry Smith   PetscFunctionBegin;
1845b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1846b4319ba4SBarry Smith   PetscFunctionReturn(0);
1847b4319ba4SBarry Smith }
1848b4319ba4SBarry Smith 
1849a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1850b4319ba4SBarry Smith {
1851b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1852dfbe8321SBarry Smith   PetscErrorCode ierr;
1853b4319ba4SBarry Smith 
1854b4319ba4SBarry Smith   PetscFunctionBegin;
1855b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1856872cf891SStefano Zampini   /* fix for local empty rows/cols */
1857872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
1858872cf891SStefano Zampini     Mat                    newlA;
1859872cf891SStefano Zampini     ISLocalToGlobalMapping l2g;
1860872cf891SStefano Zampini     IS                     tis;
1861872cf891SStefano Zampini     const PetscScalar      *v;
1862872cf891SStefano Zampini     PetscInt               i,n,cf,*loce,*locf;
1863872cf891SStefano Zampini     PetscBool              sym;
1864872cf891SStefano Zampini 
1865872cf891SStefano Zampini     ierr = MatGetRowMaxAbs(is->A,is->y,NULL);CHKERRQ(ierr);
1866872cf891SStefano Zampini     ierr = MatIsSymmetric(is->A,PETSC_SMALL,&sym);CHKERRQ(ierr);
1867872cf891SStefano Zampini     if (!sym) SETERRQ(PetscObjectComm((PetscObject)is->A),PETSC_ERR_SUP,"Not yet implemented for unsymmetric case");
1868872cf891SStefano Zampini     ierr = VecGetLocalSize(is->y,&n);CHKERRQ(ierr);
1869872cf891SStefano Zampini     ierr = PetscMalloc1(n,&loce);CHKERRQ(ierr);
1870872cf891SStefano Zampini     ierr = PetscMalloc1(n,&locf);CHKERRQ(ierr);
1871872cf891SStefano Zampini     ierr = VecGetArrayRead(is->y,&v);CHKERRQ(ierr);
1872872cf891SStefano Zampini     for (i=0,cf=0;i<n;i++) {
1873872cf891SStefano Zampini       if (v[i] == 0.0) {
1874872cf891SStefano Zampini         loce[i] = -1;
1875872cf891SStefano Zampini       } else {
1876872cf891SStefano Zampini         loce[i]    = cf;
1877872cf891SStefano Zampini         locf[cf++] = i;
1878872cf891SStefano Zampini       }
1879872cf891SStefano Zampini     }
1880872cf891SStefano Zampini     ierr = VecRestoreArrayRead(is->y,&v);CHKERRQ(ierr);
1881872cf891SStefano Zampini     /* extract valid submatrix */
1882872cf891SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A),cf,locf,PETSC_USE_POINTER,&tis);CHKERRQ(ierr);
1883e5b89577SStefano Zampini     ierr = MatCreateSubMatrix(is->A,tis,tis,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
1884872cf891SStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
1885872cf891SStefano Zampini     /* attach local l2g map for successive calls of MatSetValues */
1886872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is->A),1,n,loce,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
1887872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(newlA,l2g,l2g);CHKERRQ(ierr);
1888872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
1889872cf891SStefano Zampini     /* flag MatSetValues */
1890872cf891SStefano Zampini     is->usesetlocal = PETSC_TRUE;
1891872cf891SStefano Zampini     /* attach new global l2g map */
1892872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,cf,locf,locf);CHKERRQ(ierr);
1893872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,cf,locf,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
1894872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(A,l2g,l2g);CHKERRQ(ierr);
1895872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
1896872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
1897872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
1898872cf891SStefano Zampini   }
1899872cf891SStefano Zampini   is->locempty = PETSC_FALSE;
1900b4319ba4SBarry Smith   PetscFunctionReturn(0);
1901b4319ba4SBarry Smith }
1902b4319ba4SBarry Smith 
1903a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1904b4319ba4SBarry Smith {
1905b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1906b4319ba4SBarry Smith 
1907b4319ba4SBarry Smith   PetscFunctionBegin;
1908b4319ba4SBarry Smith   *local = is->A;
1909b4319ba4SBarry Smith   PetscFunctionReturn(0);
1910b4319ba4SBarry Smith }
1911b4319ba4SBarry Smith 
19123b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
19133b3b1effSJed Brown {
19143b3b1effSJed Brown   PetscFunctionBegin;
19153b3b1effSJed Brown   *local = NULL;
19163b3b1effSJed Brown   PetscFunctionReturn(0);
19173b3b1effSJed Brown }
19183b3b1effSJed Brown 
1919b4319ba4SBarry Smith /*@
1920b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1921b4319ba4SBarry Smith 
1922b4319ba4SBarry Smith   Input Parameter:
1923b4319ba4SBarry Smith .  mat - the matrix
1924b4319ba4SBarry Smith 
1925b4319ba4SBarry Smith   Output Parameter:
1926eb82efa4SStefano Zampini .  local - the local matrix
1927b4319ba4SBarry Smith 
1928b4319ba4SBarry Smith   Level: advanced
1929b4319ba4SBarry Smith 
1930b4319ba4SBarry Smith   Notes:
1931b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1932b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1933b4319ba4SBarry Smith   of the MatSetValues() operation.
1934b4319ba4SBarry Smith 
19353b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
193696a6f129SJed Brown 
1937b4319ba4SBarry Smith .seealso: MATIS
1938b4319ba4SBarry Smith @*/
19397087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1940b4319ba4SBarry Smith {
19414ac538c5SBarry Smith   PetscErrorCode ierr;
1942b4319ba4SBarry Smith 
1943b4319ba4SBarry Smith   PetscFunctionBegin;
19440700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1945b4319ba4SBarry Smith   PetscValidPointer(local,2);
19464ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1947b4319ba4SBarry Smith   PetscFunctionReturn(0);
1948b4319ba4SBarry Smith }
1949b4319ba4SBarry Smith 
19503b3b1effSJed Brown /*@
19513b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
19523b3b1effSJed Brown 
19533b3b1effSJed Brown   Input Parameter:
19543b3b1effSJed Brown .  mat - the matrix
19553b3b1effSJed Brown 
19563b3b1effSJed Brown   Output Parameter:
19573b3b1effSJed Brown .  local - the local matrix
19583b3b1effSJed Brown 
19593b3b1effSJed Brown   Level: advanced
19603b3b1effSJed Brown 
19613b3b1effSJed Brown .seealso: MATIS
19623b3b1effSJed Brown @*/
19633b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
19643b3b1effSJed Brown {
19653b3b1effSJed Brown   PetscErrorCode ierr;
19663b3b1effSJed Brown 
19673b3b1effSJed Brown   PetscFunctionBegin;
19683b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
19693b3b1effSJed Brown   PetscValidPointer(local,2);
19703b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
19713b3b1effSJed Brown   PetscFunctionReturn(0);
19723b3b1effSJed Brown }
19733b3b1effSJed Brown 
1974a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
19753b03a366Sstefano_zampini {
19763b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
19773b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
19783b03a366Sstefano_zampini   PetscErrorCode ierr;
19793b03a366Sstefano_zampini 
19803b03a366Sstefano_zampini   PetscFunctionBegin;
19814e4c7dbeSStefano Zampini   if (is->A) {
19823b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
19833b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1984f0ae7da4SStefano 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);
19854e4c7dbeSStefano Zampini   }
19863b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
19873b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
19883b03a366Sstefano_zampini   is->A = local;
19893b03a366Sstefano_zampini   PetscFunctionReturn(0);
19903b03a366Sstefano_zampini }
19913b03a366Sstefano_zampini 
19923b03a366Sstefano_zampini /*@
1993eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
19943b03a366Sstefano_zampini 
19953b03a366Sstefano_zampini   Input Parameter:
19963b03a366Sstefano_zampini .  mat - the matrix
1997eb82efa4SStefano Zampini .  local - the local matrix
19983b03a366Sstefano_zampini 
19993b03a366Sstefano_zampini   Output Parameter:
20003b03a366Sstefano_zampini 
20013b03a366Sstefano_zampini   Level: advanced
20023b03a366Sstefano_zampini 
20033b03a366Sstefano_zampini   Notes:
20043b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
20053b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
20063b03a366Sstefano_zampini 
20073b03a366Sstefano_zampini .seealso: MATIS
20083b03a366Sstefano_zampini @*/
20093b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
20103b03a366Sstefano_zampini {
20113b03a366Sstefano_zampini   PetscErrorCode ierr;
20123b03a366Sstefano_zampini 
20133b03a366Sstefano_zampini   PetscFunctionBegin;
20143b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2015b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
20163b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
20173b03a366Sstefano_zampini   PetscFunctionReturn(0);
20183b03a366Sstefano_zampini }
20193b03a366Sstefano_zampini 
2020a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
20216726f965SBarry Smith {
20226726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
20236726f965SBarry Smith   PetscErrorCode ierr;
20246726f965SBarry Smith 
20256726f965SBarry Smith   PetscFunctionBegin;
20266726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
20276726f965SBarry Smith   PetscFunctionReturn(0);
20286726f965SBarry Smith }
20296726f965SBarry Smith 
2030a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
20312e74eeadSLisandro Dalcin {
20322e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20332e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20342e74eeadSLisandro Dalcin 
20352e74eeadSLisandro Dalcin   PetscFunctionBegin;
20362e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
20372e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20382e74eeadSLisandro Dalcin }
20392e74eeadSLisandro Dalcin 
2040a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
20412e74eeadSLisandro Dalcin {
20422e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20432e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20442e74eeadSLisandro Dalcin 
20452e74eeadSLisandro Dalcin   PetscFunctionBegin;
20462e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
2047e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
20482e74eeadSLisandro Dalcin 
20492e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
20502e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
2051e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2052e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20532e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20542e74eeadSLisandro Dalcin }
20552e74eeadSLisandro Dalcin 
2056a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
20576726f965SBarry Smith {
20586726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
20596726f965SBarry Smith   PetscErrorCode ierr;
20606726f965SBarry Smith 
20616726f965SBarry Smith   PetscFunctionBegin;
20624e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
20636726f965SBarry Smith   PetscFunctionReturn(0);
20646726f965SBarry Smith }
20656726f965SBarry Smith 
2066f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
2067f26d0771SStefano Zampini {
2068f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
2069f26d0771SStefano Zampini   Mat_IS         *x;
2070f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2071f26d0771SStefano Zampini   PetscBool      ismatis;
2072f26d0771SStefano Zampini #endif
2073f26d0771SStefano Zampini   PetscErrorCode ierr;
2074f26d0771SStefano Zampini 
2075f26d0771SStefano Zampini   PetscFunctionBegin;
2076f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2077f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
2078f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
2079f26d0771SStefano Zampini #endif
2080f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
2081f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
2082f26d0771SStefano Zampini   PetscFunctionReturn(0);
2083f26d0771SStefano Zampini }
2084f26d0771SStefano Zampini 
2085f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
2086f26d0771SStefano Zampini {
2087f26d0771SStefano Zampini   Mat                    lA;
2088f26d0771SStefano Zampini   Mat_IS                 *matis;
2089f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2090f26d0771SStefano Zampini   IS                     is;
2091f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
2092f26d0771SStefano Zampini   PetscInt               nrg;
2093f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
2094f26d0771SStefano Zampini   PetscErrorCode         ierr;
2095f26d0771SStefano Zampini 
2096f26d0771SStefano Zampini   PetscFunctionBegin;
2097f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2098f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
2099f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
2100f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
2101f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2102f0ae7da4SStefano 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);
2103f26d0771SStefano Zampini #endif
2104f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
2105f26d0771SStefano Zampini   /* map from [0,nrl) to row */
2106f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
2107f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2108f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
2109f26d0771SStefano Zampini #else
2110f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
2111f26d0771SStefano Zampini #endif
2112f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
2113f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2114f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2115f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2116f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
2117f26d0771SStefano Zampini   /* compute new l2g map for columns */
2118f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2119f26d0771SStefano Zampini     const PetscInt *cg,*cl;
2120f26d0771SStefano Zampini     PetscInt       ncg;
2121f26d0771SStefano Zampini     PetscInt       ncl;
2122f26d0771SStefano Zampini 
2123f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2124f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2125f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2126f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2127f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2128f0ae7da4SStefano 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);
2129f26d0771SStefano Zampini #endif
2130f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2131f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2132f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2133f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2134f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2135f26d0771SStefano Zampini #else
2136f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2137f26d0771SStefano Zampini #endif
2138f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2139f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2140f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2141f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2142f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2143f26d0771SStefano Zampini   } else {
2144f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2145f26d0771SStefano Zampini     cl2g = rl2g;
2146f26d0771SStefano Zampini   }
2147f26d0771SStefano Zampini   /* create the MATIS submatrix */
2148f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2149f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2150f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2151f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2152b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2153f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2154f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2155f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2156f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2157f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2158f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2159f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2160f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2161f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2162f26d0771SStefano Zampini   /* remove unsupported ops */
2163f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2164f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2165f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2166f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2167f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2168f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2169f26d0771SStefano Zampini   PetscFunctionReturn(0);
2170f26d0771SStefano Zampini }
2171f26d0771SStefano Zampini 
2172872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
2173872cf891SStefano Zampini {
2174872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
2175872cf891SStefano Zampini   PetscErrorCode ierr;
2176872cf891SStefano Zampini 
2177872cf891SStefano Zampini   PetscFunctionBegin;
2178872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
2179872cf891SStefano Zampini   ierr = PetscObjectOptionsBegin((PetscObject)A);
2180872cf891SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns",NULL,a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
2181872cf891SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
2182872cf891SStefano Zampini   PetscFunctionReturn(0);
2183872cf891SStefano Zampini }
2184872cf891SStefano Zampini 
2185284134d9SBarry Smith /*@
21863c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2187284134d9SBarry Smith        process but not across processes.
2188284134d9SBarry Smith 
2189284134d9SBarry Smith    Input Parameters:
2190284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2191e176bc59SStefano Zampini .     bs      - block size of the matrix
2192df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2193e176bc59SStefano Zampini .     rmap    - local to global map for rows
2194e176bc59SStefano Zampini -     cmap    - local to global map for cols
2195284134d9SBarry Smith 
2196284134d9SBarry Smith    Output Parameter:
2197284134d9SBarry Smith .    A - the resulting matrix
2198284134d9SBarry Smith 
21998e6c10adSSatish Balay    Level: advanced
22008e6c10adSSatish Balay 
22013c212e90SHong Zhang    Notes: See MATIS for more details.
22026fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
22036fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
22043c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2205284134d9SBarry Smith 
2206284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2207284134d9SBarry Smith @*/
2208e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2209284134d9SBarry Smith {
2210284134d9SBarry Smith   PetscErrorCode ierr;
2211284134d9SBarry Smith 
2212284134d9SBarry Smith   PetscFunctionBegin;
22136fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2214284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2215284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
22166fdf41d1SStefano Zampini   if (bs > 0) {
2217284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
22186fdf41d1SStefano Zampini   }
2219284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2220e176bc59SStefano Zampini   if (rmap && cmap) {
2221e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2222e176bc59SStefano Zampini   } else if (!rmap) {
2223e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2224e176bc59SStefano Zampini   } else {
2225e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2226e176bc59SStefano Zampini   }
2227284134d9SBarry Smith   PetscFunctionReturn(0);
2228284134d9SBarry Smith }
2229284134d9SBarry Smith 
2230b4319ba4SBarry Smith /*MC
2231f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2232b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2233b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2234b4319ba4SBarry Smith    product is handled "implicitly".
2235b4319ba4SBarry Smith 
2236b4319ba4SBarry Smith    Operations Provided:
22376726f965SBarry Smith +  MatMult()
22382e74eeadSLisandro Dalcin .  MatMultAdd()
22392e74eeadSLisandro Dalcin .  MatMultTranspose()
22402e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
22416726f965SBarry Smith .  MatZeroEntries()
22426726f965SBarry Smith .  MatSetOption()
22432e74eeadSLisandro Dalcin .  MatZeroRows()
22442e74eeadSLisandro Dalcin .  MatSetValues()
224597563a80SStefano Zampini .  MatSetValuesBlocked()
22466726f965SBarry Smith .  MatSetValuesLocal()
224797563a80SStefano Zampini .  MatSetValuesBlockedLocal()
22482e74eeadSLisandro Dalcin .  MatScale()
22492e74eeadSLisandro Dalcin .  MatGetDiagonal()
22502b404112SStefano Zampini .  MatMissingDiagonal()
22512b404112SStefano Zampini .  MatDuplicate()
22522b404112SStefano Zampini .  MatCopy()
2253f26d0771SStefano Zampini .  MatAXPY()
22547dae84e0SHong Zhang .  MatCreateSubMatrix()
2255f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2256d7f69cd0SStefano Zampini .  MatTranspose()
22576726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2258b4319ba4SBarry Smith 
2259b4319ba4SBarry Smith    Options Database Keys:
2260b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2261b4319ba4SBarry Smith 
2262b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
2263b4319ba4SBarry Smith 
2264b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2265b4319ba4SBarry Smith 
2266b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2267eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2268b4319ba4SBarry Smith 
2269b4319ba4SBarry Smith   Level: advanced
2270b4319ba4SBarry Smith 
2271f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2272b4319ba4SBarry Smith 
2273b4319ba4SBarry Smith M*/
2274b4319ba4SBarry Smith 
22758cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2276b4319ba4SBarry Smith {
2277dfbe8321SBarry Smith   PetscErrorCode ierr;
2278b4319ba4SBarry Smith   Mat_IS         *b;
2279b4319ba4SBarry Smith 
2280b4319ba4SBarry Smith   PetscFunctionBegin;
2281b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2282b4319ba4SBarry Smith   A->data = (void*)b;
2283b4319ba4SBarry Smith 
2284e176bc59SStefano Zampini   /* matrix ops */
2285e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2286b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
22872e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
22882e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
22892e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2290b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2291b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
22922e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
229398921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2294b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2295f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
22962e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2297f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2298b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2299b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2300b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
23016726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
23022e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
23032e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
23046726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
230569796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
230669796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
230745471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2308ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
23096bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
23102b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2311659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
23127dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
2313f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
23143fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
23153fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2316d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
23177fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
2318ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
2319872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
2320b4319ba4SBarry Smith 
2321b7ce53b6SStefano Zampini   /* special MATIS functions */
2322bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
23233b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
2324bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2325b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
23262e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2327cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
232817667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2329b4319ba4SBarry Smith   PetscFunctionReturn(0);
2330b4319ba4SBarry Smith }
2331