xref: /petsc/src/mat/impls/is/matis.c (revision 1670daf91c75291fcc50369ad065f3eece720e4b)
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*/
1128f4e0baSStefano Zampini 
12f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
13f26d0771SStefano Zampini 
14a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat);
15a72627d2SStefano Zampini 
1628f4e0baSStefano Zampini #undef __FUNCT__
175e3038f0Sstefano_zampini #define __FUNCT__ "MatConvert_Nest_IS"
185e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
195e3038f0Sstefano_zampini {
205e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
215e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
225e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
235e3038f0Sstefano_zampini   MPI_Comm               comm;
245e3038f0Sstefano_zampini   PetscInt               *lr,*lc,*lrb,*lcb,*l2gidxs;
255e3038f0Sstefano_zampini   PetscInt               sti,stl,i,j,nr,nc,rbs,cbs;
265e3038f0Sstefano_zampini   PetscBool              convert,lreuse;
275e3038f0Sstefano_zampini   PetscErrorCode         ierr;
285e3038f0Sstefano_zampini 
295e3038f0Sstefano_zampini   PetscFunctionBeginUser;
305e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
315e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
325e3038f0Sstefano_zampini   rnest  = NULL;
335e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
345e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
355e3038f0Sstefano_zampini 
365e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
375e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
385e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
395e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
405e3038f0Sstefano_zampini     if (isnest) {
415e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
425e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
435e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
445e3038f0Sstefano_zampini     }
455e3038f0Sstefano_zampini   }
465e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
475e3038f0Sstefano_zampini   ierr = PetscCalloc4(nr,&lr,nc,&lc,nr,&lrb,nc,&lcb);CHKERRQ(ierr);
485e3038f0Sstefano_zampini   ierr = PetscCalloc5(nr,&isrow,nc,&iscol,
495e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
505e3038f0Sstefano_zampini                       nr*nc,&snest);CHKERRQ(ierr);
515e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
525e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
535e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
545e3038f0Sstefano_zampini       PetscBool ismatis;
555e3038f0Sstefano_zampini       PetscInt  l1,l2,ij=i*nc+j;
565e3038f0Sstefano_zampini 
575e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
585e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
595e3038f0Sstefano_zampini 
605e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
615e3038f0Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
625e3038f0Sstefano_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);
635e3038f0Sstefano_zampini 
645e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
655e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
665e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
675e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
685e3038f0Sstefano_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);
695e3038f0Sstefano_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);
705e3038f0Sstefano_zampini       lr[i] = l1;
715e3038f0Sstefano_zampini       lc[j] = l2;
725e3038f0Sstefano_zampini       ierr  = MatGetBlockSizes(snest[ij],&l1,&l2);CHKERRQ(ierr);
735e3038f0Sstefano_zampini       if (lrb[i] && l1 != lrb[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid block size %D != %D",i,j,lrb[i],l1);
745e3038f0Sstefano_zampini       if (lcb[j] && l2 != lcb[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid block size %D != %D",i,j,lcb[j],l2);
755e3038f0Sstefano_zampini       lrb[i] = l1;
765e3038f0Sstefano_zampini       lcb[j] = l2;
775e3038f0Sstefano_zampini 
785e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
795e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
805e3038f0Sstefano_zampini     }
815e3038f0Sstefano_zampini   }
825e3038f0Sstefano_zampini 
835e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
845e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
855e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
865e3038f0Sstefano_zampini     rl2g = NULL;
875e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
885e3038f0Sstefano_zampini       PetscInt n1,n2;
895e3038f0Sstefano_zampini 
905e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
915e3038f0Sstefano_zampini       ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
925e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
935e3038f0Sstefano_zampini       if (!n1) continue;
945e3038f0Sstefano_zampini       if (!rl2g) {
955e3038f0Sstefano_zampini         rl2g = cl2g;
965e3038f0Sstefano_zampini       } else {
975e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
985e3038f0Sstefano_zampini         PetscBool      same;
995e3038f0Sstefano_zampini 
1005e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
1015e3038f0Sstefano_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);
1025e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
1035e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
1045e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
1055e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
1065e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
1075e3038f0Sstefano_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);
1085e3038f0Sstefano_zampini       }
1095e3038f0Sstefano_zampini     }
1105e3038f0Sstefano_zampini   }
1115e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
1125e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
1135e3038f0Sstefano_zampini     rl2g = NULL;
1145e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
1155e3038f0Sstefano_zampini       PetscInt n1,n2;
1165e3038f0Sstefano_zampini 
1175e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
1185e3038f0Sstefano_zampini       ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
1195e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
1205e3038f0Sstefano_zampini       if (!n1) continue;
1215e3038f0Sstefano_zampini       if (!rl2g) {
1225e3038f0Sstefano_zampini         rl2g = cl2g;
1235e3038f0Sstefano_zampini       } else {
1245e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
1255e3038f0Sstefano_zampini         PetscBool      same;
1265e3038f0Sstefano_zampini 
1275e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
1285e3038f0Sstefano_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);
1295e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
1305e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
1315e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
1325e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
1335e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
1345e3038f0Sstefano_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);
1355e3038f0Sstefano_zampini       }
1365e3038f0Sstefano_zampini     }
1375e3038f0Sstefano_zampini   }
1385e3038f0Sstefano_zampini #endif
1395e3038f0Sstefano_zampini 
1405e3038f0Sstefano_zampini   B = NULL;
1415e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
1425e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
1435e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
1445e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
1455e3038f0Sstefano_zampini     for (i=0,sti=0,stl=0;i<nr;i++) {
1465e3038f0Sstefano_zampini       Mat            usedmat;
1475e3038f0Sstefano_zampini       Mat_IS         *matis;
1485e3038f0Sstefano_zampini       const PetscInt *idxs;
1495e3038f0Sstefano_zampini       PetscInt       n = lr[i]/lrb[i];
1505e3038f0Sstefano_zampini 
1515e3038f0Sstefano_zampini       /* local IS for local NEST */
1525e3038f0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr);
1535e3038f0Sstefano_zampini       sti  += n;
1545e3038f0Sstefano_zampini 
1555e3038f0Sstefano_zampini       /* l2gmap */
1565e3038f0Sstefano_zampini       j = 0;
1575e3038f0Sstefano_zampini       usedmat = nest[i][j];
1585e3038f0Sstefano_zampini       while (!usedmat && j < nc) usedmat = nest[i][j++];
1595e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
1605e3038f0Sstefano_zampini       if (!matis->sf) {
1615e3038f0Sstefano_zampini         ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr);
1625e3038f0Sstefano_zampini       }
1635e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
1645e3038f0Sstefano_zampini       ierr  = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
1655e3038f0Sstefano_zampini       ierr  = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
1665e3038f0Sstefano_zampini       ierr  = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
1675e3038f0Sstefano_zampini       stl += lr[i];
1685e3038f0Sstefano_zampini     }
1695e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
1705e3038f0Sstefano_zampini 
1715e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
1725e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
1735e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
1745e3038f0Sstefano_zampini     for (i=0,sti=0,stl=0;i<nc;i++) {
1755e3038f0Sstefano_zampini       Mat            usedmat;
1765e3038f0Sstefano_zampini       Mat_IS         *matis;
1775e3038f0Sstefano_zampini       const PetscInt *idxs;
1785e3038f0Sstefano_zampini       PetscInt       n = lc[i]/lcb[i];
1795e3038f0Sstefano_zampini 
1805e3038f0Sstefano_zampini       /* local IS for local NEST */
1815e3038f0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr);
1825e3038f0Sstefano_zampini       sti  += n;
1835e3038f0Sstefano_zampini 
1845e3038f0Sstefano_zampini       /* l2gmap */
1855e3038f0Sstefano_zampini       j = 0;
1865e3038f0Sstefano_zampini       usedmat = nest[j][i];
1875e3038f0Sstefano_zampini       while (!usedmat && j < nr) usedmat = nest[j++][i];
1885e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
1895e3038f0Sstefano_zampini       if (!matis->sf) {
1905e3038f0Sstefano_zampini         ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr);
1915e3038f0Sstefano_zampini       }
1925e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
1935e3038f0Sstefano_zampini       ierr  = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
1945e3038f0Sstefano_zampini       ierr  = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
1955e3038f0Sstefano_zampini       ierr  = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
1965e3038f0Sstefano_zampini       stl += lc[i];
1975e3038f0Sstefano_zampini     }
1985e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
1995e3038f0Sstefano_zampini 
2005e3038f0Sstefano_zampini     /* Create MATIS */
2015e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
2025e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
2035e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
2045e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
2055e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
2065e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
2075e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2085e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2095e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
2105e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
2115e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
2125e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2135e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2145e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
2155e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
2165e3038f0Sstefano_zampini     } else {
2175e3038f0Sstefano_zampini       *newmat = B;
2185e3038f0Sstefano_zampini     }
2195e3038f0Sstefano_zampini   } else {
2205e3038f0Sstefano_zampini     if (lreuse) {
2215e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
2225e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
2235e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
2245e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
2255e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
2265e3038f0Sstefano_zampini           }
2275e3038f0Sstefano_zampini         }
2285e3038f0Sstefano_zampini       }
2295e3038f0Sstefano_zampini     } else {
2305e3038f0Sstefano_zampini       for (i=0,sti=0;i<nr;i++) {
2315e3038f0Sstefano_zampini         PetscInt n = lr[i]/lrb[i];
2325e3038f0Sstefano_zampini 
2335e3038f0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr);
2345e3038f0Sstefano_zampini         sti  += n;
2355e3038f0Sstefano_zampini       }
2365e3038f0Sstefano_zampini       for (i=0,sti=0;i<nc;i++) {
2375e3038f0Sstefano_zampini         PetscInt n = lc[i]/lcb[i];
2385e3038f0Sstefano_zampini 
2395e3038f0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr);
2405e3038f0Sstefano_zampini         sti  += n;
2415e3038f0Sstefano_zampini       }
2425e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
2435e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
2445e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
2455e3038f0Sstefano_zampini     }
2465e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2475e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2485e3038f0Sstefano_zampini   }
2495e3038f0Sstefano_zampini 
2505e3038f0Sstefano_zampini   /* Free workspace */
2515e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2525e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
2535e3038f0Sstefano_zampini   }
2545e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
2555e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
2565e3038f0Sstefano_zampini   }
2575e3038f0Sstefano_zampini   ierr = PetscFree4(lr,lc,lrb,lcb);CHKERRQ(ierr);
2585e3038f0Sstefano_zampini   ierr = PetscFree5(isrow,iscol,islrow,islcol,snest);CHKERRQ(ierr);
2595e3038f0Sstefano_zampini 
2605e3038f0Sstefano_zampini   /* Create local matrix in MATNEST format */
2615e3038f0Sstefano_zampini   convert = PETSC_FALSE;
2625e3038f0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
2635e3038f0Sstefano_zampini   if (convert) {
2645e3038f0Sstefano_zampini     Mat M;
2655e3038f0Sstefano_zampini 
2665e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
2675e3038f0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
2685e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
2695e3038f0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
2705e3038f0Sstefano_zampini   }
2715e3038f0Sstefano_zampini 
2725e3038f0Sstefano_zampini   PetscFunctionReturn(0);
2735e3038f0Sstefano_zampini }
2745e3038f0Sstefano_zampini 
2755e3038f0Sstefano_zampini #undef __FUNCT__
276d7f69cd0SStefano Zampini #define __FUNCT__ "MatTranspose_IS"
277d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
278d7f69cd0SStefano Zampini {
279d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
280d7f69cd0SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
281d7f69cd0SStefano Zampini   PetscBool              notset = PETSC_FALSE,cong = PETSC_TRUE;
282d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
283d7f69cd0SStefano Zampini 
284d7f69cd0SStefano Zampini   PetscFunctionBegin;
285d7f69cd0SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
286d7f69cd0SStefano Zampini     PetscBool rcong,ccong;
287d7f69cd0SStefano Zampini 
288d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr);
289d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr);
290fa520230SStefano Zampini     cong = (PetscBool)(rcong || ccong);
291d7f69cd0SStefano Zampini   }
292d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) {
293d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
294d7f69cd0SStefano Zampini   } else {
295d7f69cd0SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,&notset);CHKERRQ(ierr);
296d7f69cd0SStefano Zampini     C = *B;
297d7f69cd0SStefano Zampini   }
298d7f69cd0SStefano Zampini 
299d7f69cd0SStefano Zampini   if (!notset) {
300d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
301d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
302d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
303d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
304d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
305d7f69cd0SStefano Zampini   }
306d7f69cd0SStefano Zampini 
307d7f69cd0SStefano Zampini   /* perform local transposition */
308d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
309d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
310d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
311d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
312d7f69cd0SStefano Zampini 
313d7f69cd0SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
314d7f69cd0SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
315d7f69cd0SStefano Zampini 
316d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
317d7f69cd0SStefano Zampini     if (!cong) {
318d7f69cd0SStefano Zampini       ierr = MatDestroy(B);CHKERRQ(ierr);
319d7f69cd0SStefano Zampini     }
320d7f69cd0SStefano Zampini     *B = C;
321d7f69cd0SStefano Zampini   } else {
322d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
323d7f69cd0SStefano Zampini   }
324d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
325d7f69cd0SStefano Zampini }
326d7f69cd0SStefano Zampini 
327d7f69cd0SStefano Zampini #undef __FUNCT__
3283fd1c9e7SStefano Zampini #define __FUNCT__ "MatDiagonalSet_IS"
3293fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
3303fd1c9e7SStefano Zampini {
3313fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
3323fd1c9e7SStefano Zampini   PetscErrorCode ierr;
3333fd1c9e7SStefano Zampini 
3343fd1c9e7SStefano Zampini   PetscFunctionBegin;
3353fd1c9e7SStefano Zampini   if (!D) { /* this code branch is used by MatShift_IS */
3363fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
3373fd1c9e7SStefano Zampini   } else {
3383fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3393fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3403fd1c9e7SStefano Zampini   }
3413fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
3423fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
3433fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
3443fd1c9e7SStefano Zampini }
3453fd1c9e7SStefano Zampini 
3463fd1c9e7SStefano Zampini #undef __FUNCT__
3473fd1c9e7SStefano Zampini #define __FUNCT__ "MatShift_IS"
3483fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
3493fd1c9e7SStefano Zampini {
3503fd1c9e7SStefano Zampini   PetscErrorCode ierr;
3513fd1c9e7SStefano Zampini 
3523fd1c9e7SStefano Zampini   PetscFunctionBegin;
3533fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
3543fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
3553fd1c9e7SStefano Zampini }
3563fd1c9e7SStefano Zampini 
3573fd1c9e7SStefano Zampini #undef __FUNCT__
358f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS"
359f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
360f26d0771SStefano Zampini {
361f26d0771SStefano Zampini   PetscErrorCode ierr;
362f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
363f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
364f26d0771SStefano Zampini 
365f26d0771SStefano Zampini   PetscFunctionBegin;
366f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
367f26d0771SStefano 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);
368f26d0771SStefano Zampini #endif
369f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
370f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
371f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
372f26d0771SStefano Zampini   PetscFunctionReturn(0);
373f26d0771SStefano Zampini }
374f26d0771SStefano Zampini 
375f26d0771SStefano Zampini #undef __FUNCT__
376f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS"
377f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
378f26d0771SStefano Zampini {
379f26d0771SStefano Zampini   PetscErrorCode ierr;
380f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
381f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
382f26d0771SStefano Zampini 
383f26d0771SStefano Zampini   PetscFunctionBegin;
384f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
385f26d0771SStefano 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);
386f26d0771SStefano Zampini #endif
387f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
388f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
389f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
390f26d0771SStefano Zampini   PetscFunctionReturn(0);
391f26d0771SStefano Zampini }
392f26d0771SStefano Zampini 
393f26d0771SStefano Zampini #undef __FUNCT__
394a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private"
395f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
396a8116848SStefano Zampini {
397a8116848SStefano Zampini   PetscInt      *owners = map->range;
398a8116848SStefano Zampini   PetscInt       n      = map->n;
399a8116848SStefano Zampini   PetscSF        sf;
400a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
401a8116848SStefano Zampini   PetscSFNode   *ridxs;
402a8116848SStefano Zampini   PetscMPIInt    rank;
403a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
404a8116848SStefano Zampini   PetscErrorCode ierr;
405a8116848SStefano Zampini 
406a8116848SStefano Zampini   PetscFunctionBegin;
407a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
408a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
409a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
410a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
411a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
412a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
413a8116848SStefano Zampini     const PetscInt idx = idxs[r];
414a8116848SStefano 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);
415a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
416a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
417a8116848SStefano Zampini     }
418a8116848SStefano Zampini     ridxs[r].rank = p;
419a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
420a8116848SStefano Zampini   }
421a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
422a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
423a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
424a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
425f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
426a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
427f0ae7da4SStefano Zampini 
428f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
429a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
430a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
431a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
432a8116848SStefano Zampini     start -= cum;
433a8116848SStefano Zampini     cum = 0;
434a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
435a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
436a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
437a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
438a8116848SStefano Zampini   }
439a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
440a8116848SStefano Zampini   /* Compress and put in indices */
441a8116848SStefano Zampini   for (r = 0; r < n; ++r)
442a8116848SStefano Zampini     if (lidxs[r] >= 0) {
443a8116848SStefano Zampini       if (work) work[len] = work[r];
444a8116848SStefano Zampini       lidxs[len++] = r;
445a8116848SStefano Zampini     }
446a8116848SStefano Zampini   if (on) *on = len;
447a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
448a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
449a8116848SStefano Zampini   PetscFunctionReturn(0);
450a8116848SStefano Zampini }
451a8116848SStefano Zampini 
452a8116848SStefano Zampini #undef __FUNCT__
453a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS"
454a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
455a8116848SStefano Zampini {
456a8116848SStefano Zampini   Mat               locmat,newlocmat;
457a8116848SStefano Zampini   Mat_IS            *newmatis;
458a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
459a8116848SStefano Zampini   Vec               rtest,ltest;
460a8116848SStefano Zampini   const PetscScalar *array;
461a8116848SStefano Zampini #endif
462a8116848SStefano Zampini   const PetscInt    *idxs;
463a8116848SStefano Zampini   PetscInt          i,m,n;
464a8116848SStefano Zampini   PetscErrorCode    ierr;
465a8116848SStefano Zampini 
466a8116848SStefano Zampini   PetscFunctionBegin;
467a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
468a8116848SStefano Zampini     PetscBool ismatis;
469a8116848SStefano Zampini 
470a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
471a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
472a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
473a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
474a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
475a8116848SStefano Zampini   }
476a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
477a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
478a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
479a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
480a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
481a8116848SStefano Zampini   for (i=0;i<n;i++) {
482a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
483a8116848SStefano Zampini   }
484a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
485a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
486a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
487a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
488a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
489fd479f66SMatthew 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]));
490a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
491a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
492a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
493a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
494a8116848SStefano Zampini   for (i=0;i<n;i++) {
495a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
496a8116848SStefano Zampini   }
497a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
498a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
499a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
500a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
501a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
502fd479f66SMatthew 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]));
503a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
504a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
505a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
506a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
507a8116848SStefano Zampini #endif
508a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
509a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
510a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
511a8116848SStefano Zampini     IS                     is;
512a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
5136dd40735SStefano Zampini     PetscInt               ll,newloc;
514a8116848SStefano Zampini     MPI_Comm               comm;
515a8116848SStefano Zampini 
516a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
517a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
518a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
519a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
520a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
521a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
522a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
523a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
524f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
525a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
526a8116848SStefano Zampini     if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
527a8116848SStefano Zampini       ierr = MatISComputeSF_Private(mat);CHKERRQ(ierr);
528a8116848SStefano Zampini     }
529a8116848SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
530a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
531a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
532a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
533a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
534a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
535a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
536a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
537a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
538a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++)
539a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
540a8116848SStefano Zampini         lidxs[newloc] = i;
541a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
542a8116848SStefano Zampini       }
543a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
544a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
545a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
546a8116848SStefano Zampini     /* local is to extract local submatrix */
547a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
548a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
549a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
550a8116848SStefano Zampini       PetscBool cong;
551a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
552a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
553a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
554a8116848SStefano Zampini     }
555a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
556a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
557a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
558a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
559a8116848SStefano Zampini     } else {
560a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
561a8116848SStefano Zampini 
562a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
563a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
564f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
565a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
566a8116848SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
567a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
568a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
569a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
570a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
571a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
572a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
573a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
574a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
575a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++)
576a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
577a8116848SStefano Zampini           lidxs[newloc] = i;
578a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
579a8116848SStefano Zampini         }
580a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
581a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
582a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
583a8116848SStefano Zampini       /* local is to extract local submatrix */
584a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
585a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
586a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
587a8116848SStefano Zampini     }
588a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
589a8116848SStefano Zampini   } else {
590a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
591a8116848SStefano Zampini   }
592a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
593a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
594a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
595a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
596a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
597a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
598a8116848SStefano Zampini   }
599a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
600a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
601a8116848SStefano Zampini   PetscFunctionReturn(0);
602a8116848SStefano Zampini }
603a8116848SStefano Zampini 
604a8116848SStefano Zampini #undef __FUNCT__
6052b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS"
606a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
6072b404112SStefano Zampini {
6082b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
6092b404112SStefano Zampini   PetscBool      ismatis;
6102b404112SStefano Zampini   PetscErrorCode ierr;
6112b404112SStefano Zampini 
6122b404112SStefano Zampini   PetscFunctionBegin;
6132b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
6142b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
6152b404112SStefano Zampini   b = (Mat_IS*)B->data;
6162b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
6172b404112SStefano Zampini   PetscFunctionReturn(0);
6182b404112SStefano Zampini }
6192b404112SStefano Zampini 
6202b404112SStefano Zampini #undef __FUNCT__
6216bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS"
622a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
6236bd84002SStefano Zampini {
624527b2640SStefano Zampini   Vec               v;
625527b2640SStefano Zampini   const PetscScalar *array;
626527b2640SStefano Zampini   PetscInt          i,n;
6276bd84002SStefano Zampini   PetscErrorCode    ierr;
6286bd84002SStefano Zampini 
6296bd84002SStefano Zampini   PetscFunctionBegin;
630527b2640SStefano Zampini   *missing = PETSC_FALSE;
631527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
632527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
633527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
634527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
635527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
636527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
637527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
638527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
639527b2640SStefano Zampini   if (d) {
640527b2640SStefano Zampini     *d = -1;
641527b2640SStefano Zampini     if (*missing) {
642527b2640SStefano Zampini       PetscInt rstart;
643527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
644527b2640SStefano Zampini       *d = i+rstart;
645527b2640SStefano Zampini     }
646527b2640SStefano Zampini   }
6476bd84002SStefano Zampini   PetscFunctionReturn(0);
6486bd84002SStefano Zampini }
6496bd84002SStefano Zampini 
6506bd84002SStefano Zampini #undef __FUNCT__
65128f4e0baSStefano Zampini #define __FUNCT__ "MatISComputeSF_Private"
652a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat B)
65328f4e0baSStefano Zampini {
65428f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
65528f4e0baSStefano Zampini   const PetscInt *gidxs;
65628f4e0baSStefano Zampini   PetscErrorCode ierr;
65728f4e0baSStefano Zampini 
65828f4e0baSStefano Zampini   PetscFunctionBegin;
65928f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,&matis->sf_nleaves,NULL);CHKERRQ(ierr);
66028f4e0baSStefano Zampini   ierr = MatGetLocalSize(B,&matis->sf_nroots,NULL);CHKERRQ(ierr);
66128f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
6623bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
66328f4e0baSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,matis->sf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
6643bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
66528f4e0baSStefano Zampini   ierr = PetscMalloc2(matis->sf_nroots,&matis->sf_rootdata,matis->sf_nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
666a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
667a8116848SStefano Zampini     ierr = MatGetSize(matis->A,NULL,&matis->csf_nleaves);CHKERRQ(ierr);
668a8116848SStefano Zampini     ierr = MatGetLocalSize(B,NULL,&matis->csf_nroots);CHKERRQ(ierr);
669a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
670a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
671a8116848SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,matis->csf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
672a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
673a8116848SStefano Zampini     ierr = PetscMalloc2(matis->csf_nroots,&matis->csf_rootdata,matis->csf_nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
674a8116848SStefano Zampini   } else {
675a8116848SStefano Zampini     matis->csf = matis->sf;
676a8116848SStefano Zampini     matis->csf_nleaves = matis->sf_nleaves;
677a8116848SStefano Zampini     matis->csf_nroots = matis->sf_nroots;
678a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
679a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
680a8116848SStefano Zampini   }
68128f4e0baSStefano Zampini   PetscFunctionReturn(0);
68228f4e0baSStefano Zampini }
6832e1947a5SStefano Zampini 
6842e1947a5SStefano Zampini #undef __FUNCT__
6852e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
686eb82efa4SStefano Zampini /*@
687a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
688a88811baSStefano Zampini 
689a88811baSStefano Zampini    Collective on MPI_Comm
690a88811baSStefano Zampini 
691a88811baSStefano Zampini    Input Parameters:
692a88811baSStefano Zampini +  B - the matrix
693a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
694a88811baSStefano Zampini            (same value is used for all local rows)
695a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
696a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
697a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
698a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
699a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
700a88811baSStefano Zampini            the diagonal entry even if it is zero.
701a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
702a88811baSStefano Zampini            submatrix (same value is used for all local rows).
703a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
704a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
705a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
706a88811baSStefano Zampini            structure. The size of this array is equal to the number
707a88811baSStefano Zampini            of local rows, i.e 'm'.
708a88811baSStefano Zampini 
709a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
710a88811baSStefano Zampini 
711a88811baSStefano Zampini    Level: intermediate
712a88811baSStefano Zampini 
713a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
714a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
715a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
716a88811baSStefano Zampini 
717a88811baSStefano Zampini .keywords: matrix
718a88811baSStefano Zampini 
7193c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
720a88811baSStefano Zampini @*/
7212e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
7222e1947a5SStefano Zampini {
7232e1947a5SStefano Zampini   PetscErrorCode ierr;
7242e1947a5SStefano Zampini 
7252e1947a5SStefano Zampini   PetscFunctionBegin;
7262e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
7272e1947a5SStefano Zampini   PetscValidType(B,1);
7282e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
7292e1947a5SStefano Zampini   PetscFunctionReturn(0);
7302e1947a5SStefano Zampini }
7312e1947a5SStefano Zampini 
7322e1947a5SStefano Zampini #undef __FUNCT__
7332e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
7347230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
7352e1947a5SStefano Zampini {
7362e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
73728f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
7382e1947a5SStefano Zampini   PetscErrorCode ierr;
7392e1947a5SStefano Zampini 
7402e1947a5SStefano Zampini   PetscFunctionBegin;
7416c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
74228f4e0baSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
74328f4e0baSStefano Zampini     ierr = MatISComputeSF_Private(B);CHKERRQ(ierr);
74428f4e0baSStefano Zampini   }
7452e1947a5SStefano Zampini   if (!d_nnz) {
74628f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nz;
7472e1947a5SStefano Zampini   } else {
74828f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
7492e1947a5SStefano Zampini   }
7502e1947a5SStefano Zampini   if (!o_nnz) {
75128f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nz;
7522e1947a5SStefano Zampini   } else {
75328f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
7542e1947a5SStefano Zampini   }
75528f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
75628f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
75728f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
75828f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
75928f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves;i++) {
76028f4e0baSStefano Zampini     matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
7612e1947a5SStefano Zampini   }
76228f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
76328f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
76428f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
7652e1947a5SStefano Zampini   }
76628f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
76728f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
76828f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
7692e1947a5SStefano Zampini   }
77028f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
7712e1947a5SStefano Zampini   PetscFunctionReturn(0);
7722e1947a5SStefano Zampini }
773b4319ba4SBarry Smith 
774b4319ba4SBarry Smith #undef __FUNCT__
7753927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
7763927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
7773927de2eSStefano Zampini {
7783927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
7793927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
780ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
7813927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
7823927de2eSStefano Zampini   PetscInt        lrows,lcols;
7833927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
7843927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
7853927de2eSStefano Zampini   PetscBool       isdense,issbaij;
7863927de2eSStefano Zampini   PetscErrorCode  ierr;
7873927de2eSStefano Zampini 
7883927de2eSStefano Zampini   PetscFunctionBegin;
7893927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
7903927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
7913927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
7923927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
7933927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
7943927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
795ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
796ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
7977230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
798ecf5a873SStefano Zampini   } else {
799ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
800ecf5a873SStefano Zampini   }
801ecf5a873SStefano Zampini 
8023927de2eSStefano Zampini   if (issbaij) {
8033927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
8043927de2eSStefano Zampini   }
8053927de2eSStefano Zampini   /*
806ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
8073927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
8083927de2eSStefano Zampini   */
8093927de2eSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
8103927de2eSStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
8113927de2eSStefano Zampini   }
8123927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
8133927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
8143927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
8153927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
8163927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
8173927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
8183927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
8193927de2eSStefano Zampini       row_ownership[j] = i;
8203927de2eSStefano Zampini     }
8213927de2eSStefano Zampini   }
8227230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
8233927de2eSStefano Zampini 
8243927de2eSStefano Zampini   /*
8253927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
8263927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
8273927de2eSStefano Zampini   */
8283927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
8293927de2eSStefano Zampini   /* preallocation as a MATAIJ */
8303927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
8313927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
832ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
8333927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
8343927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
835ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
8363927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
8373927de2eSStefano Zampini           my_dnz[i] += 1;
8383927de2eSStefano Zampini         } else { /* offdiag block */
8393927de2eSStefano Zampini           my_onz[i] += 1;
8403927de2eSStefano Zampini         }
8413927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
8423927de2eSStefano Zampini         if (i != j) {
8433927de2eSStefano Zampini           owner = row_ownership[index_col];
8443927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
8453927de2eSStefano Zampini             my_dnz[j] += 1;
8463927de2eSStefano Zampini           } else {
8473927de2eSStefano Zampini             my_onz[j] += 1;
8483927de2eSStefano Zampini           }
8493927de2eSStefano Zampini         }
8503927de2eSStefano Zampini       }
8513927de2eSStefano Zampini     }
852bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
853bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
854bb1015c3SStefano Zampini     PetscBool      done;
855bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
856bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
857bb1015c3SStefano Zampini     jptr = jj;
858bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
859bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
860bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
861bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
862bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
863bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
864bb1015c3SStefano Zampini           my_dnz[i] += 1;
865bb1015c3SStefano Zampini         } else { /* offdiag block */
866bb1015c3SStefano Zampini           my_onz[i] += 1;
867bb1015c3SStefano Zampini         }
868bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
869bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
870bb1015c3SStefano Zampini           owner = row_ownership[index_col];
871bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
872bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
873bb1015c3SStefano Zampini           } else {
874bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
875bb1015c3SStefano Zampini           }
876bb1015c3SStefano Zampini         }
877bb1015c3SStefano Zampini       }
878bb1015c3SStefano Zampini     }
879bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
880bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
881bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
8823927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
8833927de2eSStefano Zampini       const PetscInt *cols;
884ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
8853927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
8863927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
8873927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
888ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
8893927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
8903927de2eSStefano Zampini           my_dnz[i] += 1;
8913927de2eSStefano Zampini         } else { /* offdiag block */
8923927de2eSStefano Zampini           my_onz[i] += 1;
8933927de2eSStefano Zampini         }
8943927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
895d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
8963927de2eSStefano Zampini           owner = row_ownership[index_col];
8973927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
898d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
8993927de2eSStefano Zampini           } else {
900d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
9013927de2eSStefano Zampini           }
9023927de2eSStefano Zampini         }
9033927de2eSStefano Zampini       }
9043927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
9053927de2eSStefano Zampini     }
9063927de2eSStefano Zampini   }
907ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
908ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
9097230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
910ecf5a873SStefano Zampini   }
9113927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
912ecf5a873SStefano Zampini 
913ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
9143927de2eSStefano Zampini   if (maxreduce) {
9153927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
9163927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
917bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
9183927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
9193927de2eSStefano Zampini   } else {
9203927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
9213927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
922bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
9233927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
9243927de2eSStefano Zampini   }
9253927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
9263927de2eSStefano Zampini 
9273927de2eSStefano Zampini   /* Resize preallocation if overestimated */
9283927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
9293927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
9303927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
9313927de2eSStefano Zampini   }
932*1670daf9Sstefano_zampini 
933*1670daf9Sstefano_zampini   /* Set preallocation */
9343927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
9353927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
9363927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
9373927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
9383927de2eSStefano Zampini   }
9393927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
9403927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
9413927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
9423927de2eSStefano Zampini   if (issbaij) {
9433927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
9443927de2eSStefano Zampini   }
9453927de2eSStefano Zampini   PetscFunctionReturn(0);
9463927de2eSStefano Zampini }
9473927de2eSStefano Zampini 
9483927de2eSStefano Zampini #undef __FUNCT__
949b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
9507230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
951b7ce53b6SStefano Zampini {
952b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
953d9a9e74cSStefano Zampini   Mat            local_mat;
954b7ce53b6SStefano Zampini   /* info on mat */
9553cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
956b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
957686e3a49SStefano Zampini   PetscBool      isdense,issbaij,isseqaij;
9587c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
959b7ce53b6SStefano Zampini   /* values insertion */
960b7ce53b6SStefano Zampini   PetscScalar    *array;
961b7ce53b6SStefano Zampini   /* work */
962b7ce53b6SStefano Zampini   PetscErrorCode ierr;
963b7ce53b6SStefano Zampini 
964b7ce53b6SStefano Zampini   PetscFunctionBegin;
965b7ce53b6SStefano Zampini   /* get info from mat */
9667c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
9677c03b4e8SStefano Zampini   if (nsubdomains == 1) {
968*1670daf9Sstefano_zampini     Mat            B;
969*1670daf9Sstefano_zampini     IS             rows,cols;
970*1670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
971*1670daf9Sstefano_zampini 
972*1670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
973*1670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
974*1670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
975*1670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
976*1670daf9Sstefano_zampini     ierr = MatConvert(matis->A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
977*1670daf9Sstefano_zampini     ierr = MatGetSubMatrix(B,rows,cols,reuse,M);CHKERRQ(ierr);
978*1670daf9Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
979*1670daf9Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
980*1670daf9Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
981*1670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
982*1670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
9837c03b4e8SStefano Zampini     PetscFunctionReturn(0);
9847c03b4e8SStefano Zampini   }
985b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
986b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
9873cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
988b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
989b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
990686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
991b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
992b7ce53b6SStefano Zampini 
993b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
994b7ce53b6SStefano Zampini     MatType     new_mat_type;
9953927de2eSStefano Zampini     PetscBool   issbaij_red;
996b7ce53b6SStefano Zampini 
997b7ce53b6SStefano Zampini     /* determining new matrix type */
998b2566f29SBarry Smith     ierr = MPIU_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
999b7ce53b6SStefano Zampini     if (issbaij_red) {
1000b7ce53b6SStefano Zampini       new_mat_type = MATSBAIJ;
1001b7ce53b6SStefano Zampini     } else {
1002b7ce53b6SStefano Zampini       if (bs>1) {
1003b7ce53b6SStefano Zampini         new_mat_type = MATBAIJ;
1004b7ce53b6SStefano Zampini       } else {
1005b7ce53b6SStefano Zampini         new_mat_type = MATAIJ;
1006b7ce53b6SStefano Zampini       }
1007b7ce53b6SStefano Zampini     }
1008b7ce53b6SStefano Zampini 
10093927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
10103cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
10113927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
10123927de2eSStefano Zampini     ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr);
10133927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1014b7ce53b6SStefano Zampini   } else {
10153cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1016b7ce53b6SStefano Zampini     /* some checks */
1017b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1018b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
10193cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
10206c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
10216c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
10226c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
10236c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
10246c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1025b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1026b7ce53b6SStefano Zampini   }
1027d9a9e74cSStefano Zampini 
1028d9a9e74cSStefano Zampini   if (issbaij) {
1029d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1030d9a9e74cSStefano Zampini   } else {
1031d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1032d9a9e74cSStefano Zampini     local_mat = matis->A;
1033d9a9e74cSStefano Zampini   }
1034686e3a49SStefano Zampini 
1035b7ce53b6SStefano Zampini   /* Set values */
1036ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1037b7ce53b6SStefano Zampini   if (isdense) { /* special case for dense local matrices */
1038ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
1039ecf5a873SStefano Zampini 
1040ecf5a873SStefano Zampini     if (local_rows != local_cols) {
1041ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
1042ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1043ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
1044ecf5a873SStefano Zampini     } else {
1045ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
1046ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1047ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
1048ecf5a873SStefano Zampini     }
1049b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1050d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
1051ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
1052d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
1053ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
1054ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
1055ecf5a873SStefano Zampini     } else {
1056ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
1057ecf5a873SStefano Zampini     }
1058686e3a49SStefano Zampini   } else if (isseqaij) {
1059ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1060686e3a49SStefano Zampini     PetscBool done;
1061686e3a49SStefano Zampini 
1062d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1063bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1064d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1065686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1066ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1067686e3a49SStefano Zampini     }
1068d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1069bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1070d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1071686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1072ecf5a873SStefano Zampini     PetscInt i;
1073c0962df8SStefano Zampini 
1074686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1075686e3a49SStefano Zampini       PetscInt       j;
1076ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1077686e3a49SStefano Zampini 
1078ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1079ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1080ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1081686e3a49SStefano Zampini     }
1082b7ce53b6SStefano Zampini   }
1083b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1084d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1085b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1086b7ce53b6SStefano Zampini   if (isdense) {
1087b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1088b7ce53b6SStefano Zampini   }
1089b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1090b7ce53b6SStefano Zampini }
1091b7ce53b6SStefano Zampini 
1092b7ce53b6SStefano Zampini #undef __FUNCT__
1093b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
1094b7ce53b6SStefano Zampini /*@
1095b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1096b7ce53b6SStefano Zampini 
1097b7ce53b6SStefano Zampini   Input Parameter:
1098b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1099b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1100b7ce53b6SStefano Zampini 
1101b7ce53b6SStefano Zampini   Output Parameter:
1102b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1103b7ce53b6SStefano Zampini 
1104b7ce53b6SStefano Zampini   Level: developer
1105b7ce53b6SStefano Zampini 
1106eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1107b7ce53b6SStefano Zampini 
1108b7ce53b6SStefano Zampini .seealso: MATIS
1109b7ce53b6SStefano Zampini @*/
1110b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1111b7ce53b6SStefano Zampini {
1112b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1113b7ce53b6SStefano Zampini 
1114b7ce53b6SStefano Zampini   PetscFunctionBegin;
1115b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1116b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1117b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1118b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1119b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1120b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
11216c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1122b7ce53b6SStefano Zampini   }
1123b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1124b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1125b7ce53b6SStefano Zampini }
1126b7ce53b6SStefano Zampini 
1127b7ce53b6SStefano Zampini #undef __FUNCT__
1128ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
1129ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1130ad6194a2SStefano Zampini {
1131ad6194a2SStefano Zampini   PetscErrorCode ierr;
1132ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1133ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1134ad6194a2SStefano Zampini   Mat            B,localmat;
1135ad6194a2SStefano Zampini 
1136ad6194a2SStefano Zampini   PetscFunctionBegin;
1137ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1138ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1139ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1140e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1141ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1142ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1143b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1144ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1145ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1146ad6194a2SStefano Zampini   *newmat = B;
1147ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1148ad6194a2SStefano Zampini }
1149ad6194a2SStefano Zampini 
1150ad6194a2SStefano Zampini #undef __FUNCT__
115169796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
1152a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
115369796d55SStefano Zampini {
115469796d55SStefano Zampini   PetscErrorCode ierr;
115569796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
115669796d55SStefano Zampini   PetscBool      local_sym;
115769796d55SStefano Zampini 
115869796d55SStefano Zampini   PetscFunctionBegin;
115969796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1160b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
116169796d55SStefano Zampini   PetscFunctionReturn(0);
116269796d55SStefano Zampini }
116369796d55SStefano Zampini 
116469796d55SStefano Zampini #undef __FUNCT__
116569796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
1166a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
116769796d55SStefano Zampini {
116869796d55SStefano Zampini   PetscErrorCode ierr;
116969796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
117069796d55SStefano Zampini   PetscBool      local_sym;
117169796d55SStefano Zampini 
117269796d55SStefano Zampini   PetscFunctionBegin;
117369796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1174b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
117569796d55SStefano Zampini   PetscFunctionReturn(0);
117669796d55SStefano Zampini }
117769796d55SStefano Zampini 
117869796d55SStefano Zampini #undef __FUNCT__
1179b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
1180a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1181b4319ba4SBarry Smith {
1182dfbe8321SBarry Smith   PetscErrorCode ierr;
1183b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1184b4319ba4SBarry Smith 
1185b4319ba4SBarry Smith   PetscFunctionBegin;
11866bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1187e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1188e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
11896bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
11906bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
11913fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1192a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1193a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1194a8116848SStefano Zampini   if (b->sf != b->csf) {
1195a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1196a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1197a8116848SStefano Zampini   }
119828f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
119928f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1200bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1201dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1202bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1203b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1204b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
12052e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1206b4319ba4SBarry Smith   PetscFunctionReturn(0);
1207b4319ba4SBarry Smith }
1208b4319ba4SBarry Smith 
1209b4319ba4SBarry Smith #undef __FUNCT__
1210b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
1211a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1212b4319ba4SBarry Smith {
1213dfbe8321SBarry Smith   PetscErrorCode ierr;
1214b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1215b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1216b4319ba4SBarry Smith 
1217b4319ba4SBarry Smith   PetscFunctionBegin;
1218b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1219e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1220e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1221b4319ba4SBarry Smith 
1222b4319ba4SBarry Smith   /* multiply the local matrix */
1223b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1224b4319ba4SBarry Smith 
1225b4319ba4SBarry Smith   /* scatter product back into global memory */
12262dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1227e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1228e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1229b4319ba4SBarry Smith   PetscFunctionReturn(0);
1230b4319ba4SBarry Smith }
1231b4319ba4SBarry Smith 
1232b4319ba4SBarry Smith #undef __FUNCT__
12332e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
1234a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
12352e74eeadSLisandro Dalcin {
1236650997f4SStefano Zampini   Vec            temp_vec;
12372e74eeadSLisandro Dalcin   PetscErrorCode ierr;
12382e74eeadSLisandro Dalcin 
12392e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1240650997f4SStefano Zampini   if (v3 != v2) {
1241650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1242650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1243650997f4SStefano Zampini   } else {
1244650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1245650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1246650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1247650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1248650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1249650997f4SStefano Zampini   }
12502e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
12512e74eeadSLisandro Dalcin }
12522e74eeadSLisandro Dalcin 
12532e74eeadSLisandro Dalcin #undef __FUNCT__
12542e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
1255a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
12562e74eeadSLisandro Dalcin {
12572e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
12582e74eeadSLisandro Dalcin   PetscErrorCode ierr;
12592e74eeadSLisandro Dalcin 
1260e176bc59SStefano Zampini   PetscFunctionBegin;
12612e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1262e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1263e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12642e74eeadSLisandro Dalcin 
12652e74eeadSLisandro Dalcin   /* multiply the local matrix */
1266e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
12672e74eeadSLisandro Dalcin 
12682e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1269e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1270e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1271e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12722e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
12732e74eeadSLisandro Dalcin }
12742e74eeadSLisandro Dalcin 
12752e74eeadSLisandro Dalcin #undef __FUNCT__
12762e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
1277a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
12782e74eeadSLisandro Dalcin {
1279650997f4SStefano Zampini   Vec            temp_vec;
12802e74eeadSLisandro Dalcin   PetscErrorCode ierr;
12812e74eeadSLisandro Dalcin 
12822e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1283650997f4SStefano Zampini   if (v3 != v2) {
1284650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1285650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1286650997f4SStefano Zampini   } else {
1287650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1288650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1289650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1290650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1291650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1292650997f4SStefano Zampini   }
12932e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
12942e74eeadSLisandro Dalcin }
12952e74eeadSLisandro Dalcin 
12962e74eeadSLisandro Dalcin #undef __FUNCT__
1297b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
1298a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1299b4319ba4SBarry Smith {
1300b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1301dfbe8321SBarry Smith   PetscErrorCode ierr;
1302b4319ba4SBarry Smith   PetscViewer    sviewer;
1303b4319ba4SBarry Smith 
1304b4319ba4SBarry Smith   PetscFunctionBegin;
13053f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1306b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
13073f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
13086e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1309b4319ba4SBarry Smith   PetscFunctionReturn(0);
1310b4319ba4SBarry Smith }
1311b4319ba4SBarry Smith 
1312b4319ba4SBarry Smith #undef __FUNCT__
1313b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
1314a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1315b4319ba4SBarry Smith {
1316dfbe8321SBarry Smith   PetscErrorCode ierr;
1317e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1318b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1319b4319ba4SBarry Smith   IS             from,to;
1320e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1321b4319ba4SBarry Smith 
1322b4319ba4SBarry Smith   PetscFunctionBegin;
1323784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1324e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
13253bbff08aSStefano Zampini   /* Destroy any previous data */
132670cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
132770cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
13283fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1329e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1330e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
13311c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
133228f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
133328f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
13343bbff08aSStefano Zampini 
13353bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1336fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1337fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1338fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1339fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1340b4319ba4SBarry Smith 
1341b4319ba4SBarry Smith   /* Create the local matrix A */
1342e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1343e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1344e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1345e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1346f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1347e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1348e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1349e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1350ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1351ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1352b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1353b4319ba4SBarry Smith 
1354f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1355b4319ba4SBarry Smith     /* Create the local work vectors */
13563bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1357b4319ba4SBarry Smith 
1358e176bc59SStefano Zampini     /* setup the global to local scatters */
1359e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1360e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1361784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1362e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1363e176bc59SStefano Zampini     if (rmapping != cmapping) {
1364e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1365e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1366e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1367e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1368e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1369e176bc59SStefano Zampini     } else {
1370e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1371e176bc59SStefano Zampini       is->cctx = is->rctx;
1372e176bc59SStefano Zampini     }
13733fd1c9e7SStefano Zampini 
13743fd1c9e7SStefano Zampini     /* interface counter vector (local) */
13753fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
13763fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
13773fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13783fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13793fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13803fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13813fd1c9e7SStefano Zampini 
13823fd1c9e7SStefano Zampini     /* free workspace */
1383e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1384e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
13856bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
13866bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1387f26d0771SStefano Zampini   }
138848ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1389b4319ba4SBarry Smith   PetscFunctionReturn(0);
1390b4319ba4SBarry Smith }
1391b4319ba4SBarry Smith 
13922e74eeadSLisandro Dalcin #undef __FUNCT__
13932e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
1394a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
13952e74eeadSLisandro Dalcin {
13962e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
13972e74eeadSLisandro Dalcin   PetscErrorCode ierr;
139897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
139997563a80SStefano Zampini   PetscInt       i,zm,zn;
140097563a80SStefano Zampini #endif
1401f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
14022e74eeadSLisandro Dalcin 
14032e74eeadSLisandro Dalcin   PetscFunctionBegin;
14042e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1405f26d0771SStefano 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);
140697563a80SStefano Zampini   /* count negative indices */
140797563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
140897563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
14092e74eeadSLisandro Dalcin #endif
141097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
141197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
141297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
141397563a80SStefano Zampini   /* count negative indices (should be the same as before) */
141497563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
141597563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
141697563a80SStefano 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");
141797563a80SStefano 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");
141897563a80SStefano Zampini #endif
14192e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
14202e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14212e74eeadSLisandro Dalcin }
14222e74eeadSLisandro Dalcin 
1423b4319ba4SBarry Smith #undef __FUNCT__
142497563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS"
1425a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
142697563a80SStefano Zampini {
142797563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
142897563a80SStefano Zampini   PetscErrorCode ierr;
142997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
143097563a80SStefano Zampini   PetscInt       i,zm,zn;
143197563a80SStefano Zampini #endif
1432f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
143397563a80SStefano Zampini 
143497563a80SStefano Zampini   PetscFunctionBegin;
143597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1436f26d0771SStefano 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);
143797563a80SStefano Zampini   /* count negative indices */
143897563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
143997563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
144097563a80SStefano Zampini #endif
144197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
144297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
144397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
144497563a80SStefano Zampini   /* count negative indices (should be the same as before) */
144597563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
144697563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
144797563a80SStefano 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");
144897563a80SStefano 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");
144997563a80SStefano Zampini #endif
145097563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
145197563a80SStefano Zampini   PetscFunctionReturn(0);
145297563a80SStefano Zampini }
145397563a80SStefano Zampini 
145497563a80SStefano Zampini #undef __FUNCT__
1455b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
1456a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1457b4319ba4SBarry Smith {
1458dfbe8321SBarry Smith   PetscErrorCode ierr;
1459b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1460b4319ba4SBarry Smith 
1461b4319ba4SBarry Smith   PetscFunctionBegin;
1462b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1463b4319ba4SBarry Smith   PetscFunctionReturn(0);
1464b4319ba4SBarry Smith }
1465b4319ba4SBarry Smith 
1466b4319ba4SBarry Smith #undef __FUNCT__
1467f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
1468a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1469f0006bf2SLisandro Dalcin {
1470f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1471f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1472f0006bf2SLisandro Dalcin 
1473f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1474f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1475f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1476f0006bf2SLisandro Dalcin }
1477f0006bf2SLisandro Dalcin 
1478f0006bf2SLisandro Dalcin #undef __FUNCT__
1479f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private"
1480f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1481f0ae7da4SStefano Zampini {
1482f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1483f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1484f0ae7da4SStefano Zampini 
1485f0ae7da4SStefano Zampini   PetscFunctionBegin;
1486f0ae7da4SStefano Zampini   if (!n) {
1487f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1488f0ae7da4SStefano Zampini   } else {
1489f0ae7da4SStefano Zampini     PetscInt i;
1490f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1491f0ae7da4SStefano Zampini 
1492f0ae7da4SStefano Zampini     if (columns) {
1493f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1494f0ae7da4SStefano Zampini     } else {
1495f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1496f0ae7da4SStefano Zampini     }
1497f0ae7da4SStefano Zampini     if (diag != 0.) {
1498f0ae7da4SStefano Zampini       const PetscScalar *array;
1499f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1500f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1501f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1502f0ae7da4SStefano Zampini       }
1503f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1504f0ae7da4SStefano Zampini     }
1505f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1506f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1507f0ae7da4SStefano Zampini   }
1508f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1509f0ae7da4SStefano Zampini }
1510f0ae7da4SStefano Zampini 
1511f0ae7da4SStefano Zampini #undef __FUNCT__
1512f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS"
1513f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
15142e74eeadSLisandro Dalcin {
15156e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
15166e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
15176e520ac8SStefano Zampini   PetscInt       *lrows;
15182e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15192e74eeadSLisandro Dalcin 
15202e74eeadSLisandro Dalcin   PetscFunctionBegin;
1521f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1522f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1523f0ae7da4SStefano Zampini     PetscBool cong;
1524f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1525f0ae7da4SStefano 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");
1526f0ae7da4SStefano 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");
1527f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1528f0ae7da4SStefano Zampini   }
1529f0ae7da4SStefano Zampini #endif
15306e520ac8SStefano Zampini   /* get locally owned rows */
1531f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
15326e520ac8SStefano Zampini   /* fix right hand side if needed */
15336e520ac8SStefano Zampini   if (x && b) {
15346e520ac8SStefano Zampini     const PetscScalar *xx;
15356e520ac8SStefano Zampini     PetscScalar       *bb;
15366e520ac8SStefano Zampini 
15376e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
15386e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
15396e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
15406e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
15416e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
15422e74eeadSLisandro Dalcin   }
15436e520ac8SStefano Zampini   /* get rows associated to the local matrices */
15446e520ac8SStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
15456e520ac8SStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
15466e520ac8SStefano Zampini   }
15476e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
15486e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
15496e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
15506e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
15516e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
15526e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
15536e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
15546e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
15556e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1556f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
15576e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
15582e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15592e74eeadSLisandro Dalcin }
15602e74eeadSLisandro Dalcin 
15612e74eeadSLisandro Dalcin #undef __FUNCT__
1562f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS"
1563f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1564b4319ba4SBarry Smith {
1565dfbe8321SBarry Smith   PetscErrorCode ierr;
1566b4319ba4SBarry Smith 
1567b4319ba4SBarry Smith   PetscFunctionBegin;
1568f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1569f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1570f0ae7da4SStefano Zampini }
15712205254eSKarl Rupp 
1572f0ae7da4SStefano Zampini #undef __FUNCT__
1573f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS"
1574f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1575f0ae7da4SStefano Zampini {
1576f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1577f0ae7da4SStefano Zampini 
1578f0ae7da4SStefano Zampini   PetscFunctionBegin;
1579f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1580b4319ba4SBarry Smith   PetscFunctionReturn(0);
1581b4319ba4SBarry Smith }
1582b4319ba4SBarry Smith 
1583b4319ba4SBarry Smith #undef __FUNCT__
1584b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
1585a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1586b4319ba4SBarry Smith {
1587b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1588dfbe8321SBarry Smith   PetscErrorCode ierr;
1589b4319ba4SBarry Smith 
1590b4319ba4SBarry Smith   PetscFunctionBegin;
1591b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1592b4319ba4SBarry Smith   PetscFunctionReturn(0);
1593b4319ba4SBarry Smith }
1594b4319ba4SBarry Smith 
1595b4319ba4SBarry Smith #undef __FUNCT__
1596b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
1597a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1598b4319ba4SBarry Smith {
1599b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1600dfbe8321SBarry Smith   PetscErrorCode ierr;
1601b4319ba4SBarry Smith 
1602b4319ba4SBarry Smith   PetscFunctionBegin;
1603b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1604b4319ba4SBarry Smith   PetscFunctionReturn(0);
1605b4319ba4SBarry Smith }
1606b4319ba4SBarry Smith 
1607b4319ba4SBarry Smith #undef __FUNCT__
1608b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
1609a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1610b4319ba4SBarry Smith {
1611b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1612b4319ba4SBarry Smith 
1613b4319ba4SBarry Smith   PetscFunctionBegin;
1614b4319ba4SBarry Smith   *local = is->A;
1615b4319ba4SBarry Smith   PetscFunctionReturn(0);
1616b4319ba4SBarry Smith }
1617b4319ba4SBarry Smith 
1618b4319ba4SBarry Smith #undef __FUNCT__
1619b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
1620b4319ba4SBarry Smith /*@
1621b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1622b4319ba4SBarry Smith 
1623b4319ba4SBarry Smith   Input Parameter:
1624b4319ba4SBarry Smith .  mat - the matrix
1625b4319ba4SBarry Smith 
1626b4319ba4SBarry Smith   Output Parameter:
1627eb82efa4SStefano Zampini .  local - the local matrix
1628b4319ba4SBarry Smith 
1629b4319ba4SBarry Smith   Level: advanced
1630b4319ba4SBarry Smith 
1631b4319ba4SBarry Smith   Notes:
1632b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1633b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1634b4319ba4SBarry Smith   of the MatSetValues() operation.
1635b4319ba4SBarry Smith 
1636b4319ba4SBarry Smith .seealso: MATIS
1637b4319ba4SBarry Smith @*/
16387087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1639b4319ba4SBarry Smith {
16404ac538c5SBarry Smith   PetscErrorCode ierr;
1641b4319ba4SBarry Smith 
1642b4319ba4SBarry Smith   PetscFunctionBegin;
16430700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1644b4319ba4SBarry Smith   PetscValidPointer(local,2);
16454ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1646b4319ba4SBarry Smith   PetscFunctionReturn(0);
1647b4319ba4SBarry Smith }
1648b4319ba4SBarry Smith 
16493b03a366Sstefano_zampini #undef __FUNCT__
16503b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
1651a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
16523b03a366Sstefano_zampini {
16533b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
16543b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
16553b03a366Sstefano_zampini   PetscErrorCode ierr;
16563b03a366Sstefano_zampini 
16573b03a366Sstefano_zampini   PetscFunctionBegin;
16584e4c7dbeSStefano Zampini   if (is->A) {
16593b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
16603b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1661f0ae7da4SStefano 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);
16624e4c7dbeSStefano Zampini   }
16633b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
16643b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
16653b03a366Sstefano_zampini   is->A = local;
16663b03a366Sstefano_zampini   PetscFunctionReturn(0);
16673b03a366Sstefano_zampini }
16683b03a366Sstefano_zampini 
16693b03a366Sstefano_zampini #undef __FUNCT__
16703b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
16713b03a366Sstefano_zampini /*@
1672eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
16733b03a366Sstefano_zampini 
16743b03a366Sstefano_zampini   Input Parameter:
16753b03a366Sstefano_zampini .  mat - the matrix
1676eb82efa4SStefano Zampini .  local - the local matrix
16773b03a366Sstefano_zampini 
16783b03a366Sstefano_zampini   Output Parameter:
16793b03a366Sstefano_zampini 
16803b03a366Sstefano_zampini   Level: advanced
16813b03a366Sstefano_zampini 
16823b03a366Sstefano_zampini   Notes:
16833b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
16843b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
16853b03a366Sstefano_zampini 
16863b03a366Sstefano_zampini .seealso: MATIS
16873b03a366Sstefano_zampini @*/
16883b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
16893b03a366Sstefano_zampini {
16903b03a366Sstefano_zampini   PetscErrorCode ierr;
16913b03a366Sstefano_zampini 
16923b03a366Sstefano_zampini   PetscFunctionBegin;
16933b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1694b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
16953b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
16963b03a366Sstefano_zampini   PetscFunctionReturn(0);
16973b03a366Sstefano_zampini }
16983b03a366Sstefano_zampini 
16996726f965SBarry Smith #undef __FUNCT__
17006726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
1701a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
17026726f965SBarry Smith {
17036726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
17046726f965SBarry Smith   PetscErrorCode ierr;
17056726f965SBarry Smith 
17066726f965SBarry Smith   PetscFunctionBegin;
17076726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
17086726f965SBarry Smith   PetscFunctionReturn(0);
17096726f965SBarry Smith }
17106726f965SBarry Smith 
17116726f965SBarry Smith #undef __FUNCT__
17122e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
1713a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
17142e74eeadSLisandro Dalcin {
17152e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
17162e74eeadSLisandro Dalcin   PetscErrorCode ierr;
17172e74eeadSLisandro Dalcin 
17182e74eeadSLisandro Dalcin   PetscFunctionBegin;
17192e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
17202e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
17212e74eeadSLisandro Dalcin }
17222e74eeadSLisandro Dalcin 
17232e74eeadSLisandro Dalcin #undef __FUNCT__
17242e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
1725a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
17262e74eeadSLisandro Dalcin {
17272e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
17282e74eeadSLisandro Dalcin   PetscErrorCode ierr;
17292e74eeadSLisandro Dalcin 
17302e74eeadSLisandro Dalcin   PetscFunctionBegin;
17312e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
1732e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
17332e74eeadSLisandro Dalcin 
17342e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
17352e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
1736e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1737e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17382e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
17392e74eeadSLisandro Dalcin }
17402e74eeadSLisandro Dalcin 
17412e74eeadSLisandro Dalcin #undef __FUNCT__
17426726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
1743a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
17446726f965SBarry Smith {
17456726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
17466726f965SBarry Smith   PetscErrorCode ierr;
17476726f965SBarry Smith 
17486726f965SBarry Smith   PetscFunctionBegin;
17494e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
17506726f965SBarry Smith   PetscFunctionReturn(0);
17516726f965SBarry Smith }
17526726f965SBarry Smith 
1753284134d9SBarry Smith #undef __FUNCT__
1754f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS"
1755f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
1756f26d0771SStefano Zampini {
1757f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
1758f26d0771SStefano Zampini   Mat_IS         *x;
1759f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1760f26d0771SStefano Zampini   PetscBool      ismatis;
1761f26d0771SStefano Zampini #endif
1762f26d0771SStefano Zampini   PetscErrorCode ierr;
1763f26d0771SStefano Zampini 
1764f26d0771SStefano Zampini   PetscFunctionBegin;
1765f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1766f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
1767f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
1768f26d0771SStefano Zampini #endif
1769f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
1770f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
1771f26d0771SStefano Zampini   PetscFunctionReturn(0);
1772f26d0771SStefano Zampini }
1773f26d0771SStefano Zampini 
1774f26d0771SStefano Zampini #undef __FUNCT__
1775f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS"
1776f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
1777f26d0771SStefano Zampini {
1778f26d0771SStefano Zampini   Mat                    lA;
1779f26d0771SStefano Zampini   Mat_IS                 *matis;
1780f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
1781f26d0771SStefano Zampini   IS                     is;
1782f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
1783f26d0771SStefano Zampini   PetscInt               nrg;
1784f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
1785f26d0771SStefano Zampini   PetscErrorCode         ierr;
1786f26d0771SStefano Zampini 
1787f26d0771SStefano Zampini   PetscFunctionBegin;
1788f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1789f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
1790f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
1791f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
1792f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1793f0ae7da4SStefano 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);
1794f26d0771SStefano Zampini #endif
1795f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
1796f26d0771SStefano Zampini   /* map from [0,nrl) to row */
1797f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
1798f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1799f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
1800f26d0771SStefano Zampini #else
1801f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
1802f26d0771SStefano Zampini #endif
1803f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
1804f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1805f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1806f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1807f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
1808f26d0771SStefano Zampini   /* compute new l2g map for columns */
1809f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
1810f26d0771SStefano Zampini     const PetscInt *cg,*cl;
1811f26d0771SStefano Zampini     PetscInt       ncg;
1812f26d0771SStefano Zampini     PetscInt       ncl;
1813f26d0771SStefano Zampini 
1814f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1815f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
1816f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
1817f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
1818f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1819f0ae7da4SStefano 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);
1820f26d0771SStefano Zampini #endif
1821f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
1822f26d0771SStefano Zampini     /* map from [0,ncl) to col */
1823f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
1824f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1825f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
1826f26d0771SStefano Zampini #else
1827f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
1828f26d0771SStefano Zampini #endif
1829f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
1830f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1831f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1832f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1833f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1834f26d0771SStefano Zampini   } else {
1835f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
1836f26d0771SStefano Zampini     cl2g = rl2g;
1837f26d0771SStefano Zampini   }
1838f26d0771SStefano Zampini   /* create the MATIS submatrix */
1839f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
1840f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
1841f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1842f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
1843b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
1844f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
1845f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
1846f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1847f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
1848f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
1849f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1850f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1851f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1852f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1853f26d0771SStefano Zampini   /* remove unsupported ops */
1854f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1855f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
1856f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
1857f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
1858f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
1859f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
1860f26d0771SStefano Zampini   PetscFunctionReturn(0);
1861f26d0771SStefano Zampini }
1862f26d0771SStefano Zampini 
1863f26d0771SStefano Zampini #undef __FUNCT__
1864284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
1865284134d9SBarry Smith /*@
18663c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
1867284134d9SBarry Smith        process but not across processes.
1868284134d9SBarry Smith 
1869284134d9SBarry Smith    Input Parameters:
1870284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
1871e176bc59SStefano Zampini .     bs      - block size of the matrix
1872df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
1873e176bc59SStefano Zampini .     rmap    - local to global map for rows
1874e176bc59SStefano Zampini -     cmap    - local to global map for cols
1875284134d9SBarry Smith 
1876284134d9SBarry Smith    Output Parameter:
1877284134d9SBarry Smith .    A - the resulting matrix
1878284134d9SBarry Smith 
18798e6c10adSSatish Balay    Level: advanced
18808e6c10adSSatish Balay 
18813c212e90SHong Zhang    Notes: See MATIS for more details.
18826fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
18836fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
18843c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
1885284134d9SBarry Smith 
1886284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
1887284134d9SBarry Smith @*/
1888e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
1889284134d9SBarry Smith {
1890284134d9SBarry Smith   PetscErrorCode ierr;
1891284134d9SBarry Smith 
1892284134d9SBarry Smith   PetscFunctionBegin;
18936fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
1894284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
18956fdf41d1SStefano Zampini   if (bs > 0) {
1896d3ee2243SStefano Zampini     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
18976fdf41d1SStefano Zampini   }
1898284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
1899284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
1900e176bc59SStefano Zampini   if (rmap && cmap) {
1901e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
1902e176bc59SStefano Zampini   } else if (!rmap) {
1903e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
1904e176bc59SStefano Zampini   } else {
1905e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
1906e176bc59SStefano Zampini   }
1907284134d9SBarry Smith   PetscFunctionReturn(0);
1908284134d9SBarry Smith }
1909284134d9SBarry Smith 
1910b4319ba4SBarry Smith /*MC
1911f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
1912b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
1913b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
1914b4319ba4SBarry Smith    product is handled "implicitly".
1915b4319ba4SBarry Smith 
1916b4319ba4SBarry Smith    Operations Provided:
19176726f965SBarry Smith +  MatMult()
19182e74eeadSLisandro Dalcin .  MatMultAdd()
19192e74eeadSLisandro Dalcin .  MatMultTranspose()
19202e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
19216726f965SBarry Smith .  MatZeroEntries()
19226726f965SBarry Smith .  MatSetOption()
19232e74eeadSLisandro Dalcin .  MatZeroRows()
19242e74eeadSLisandro Dalcin .  MatSetValues()
192597563a80SStefano Zampini .  MatSetValuesBlocked()
19266726f965SBarry Smith .  MatSetValuesLocal()
192797563a80SStefano Zampini .  MatSetValuesBlockedLocal()
19282e74eeadSLisandro Dalcin .  MatScale()
19292e74eeadSLisandro Dalcin .  MatGetDiagonal()
19302b404112SStefano Zampini .  MatMissingDiagonal()
19312b404112SStefano Zampini .  MatDuplicate()
19322b404112SStefano Zampini .  MatCopy()
1933f26d0771SStefano Zampini .  MatAXPY()
1934f26d0771SStefano Zampini .  MatGetSubMatrix()
1935f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
1936d7f69cd0SStefano Zampini .  MatTranspose()
19376726f965SBarry Smith -  MatSetLocalToGlobalMapping()
1938b4319ba4SBarry Smith 
1939b4319ba4SBarry Smith    Options Database Keys:
1940b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
1941b4319ba4SBarry Smith 
1942b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
1943b4319ba4SBarry Smith 
1944b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
1945b4319ba4SBarry Smith 
1946b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
1947eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
1948b4319ba4SBarry Smith 
1949b4319ba4SBarry Smith   Level: advanced
1950b4319ba4SBarry Smith 
1951f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
1952b4319ba4SBarry Smith 
1953b4319ba4SBarry Smith M*/
1954b4319ba4SBarry Smith 
1955b4319ba4SBarry Smith #undef __FUNCT__
1956b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
19578cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
1958b4319ba4SBarry Smith {
1959dfbe8321SBarry Smith   PetscErrorCode ierr;
1960b4319ba4SBarry Smith   Mat_IS         *b;
1961b4319ba4SBarry Smith 
1962b4319ba4SBarry Smith   PetscFunctionBegin;
1963b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
1964b4319ba4SBarry Smith   A->data = (void*)b;
1965b4319ba4SBarry Smith 
1966e176bc59SStefano Zampini   /* matrix ops */
1967e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1968b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
19692e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
19702e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
19712e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
1972b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
1973b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
19742e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
197598921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
1976b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
1977f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
19782e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
1979f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
1980b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
1981b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
1982b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
19836726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
19842e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
19852e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
19866726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
198769796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
198869796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
1989ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
19906bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
19912b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
1992659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
1993a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
1994f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
19953fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
19963fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
1997d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
1998b4319ba4SBarry Smith 
1999b7ce53b6SStefano Zampini   /* special MATIS functions */
2000bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
2001bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2002b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
20032e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
200417667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2005b4319ba4SBarry Smith   PetscFunctionReturn(0);
2006b4319ba4SBarry Smith }
2007