xref: /petsc/src/mat/impls/is/matis.c (revision 9e7b2b254cbceb4abc4abed5d426b9e29b98e2bb)
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__
177fa8f2d3SStefano Zampini #define __FUNCT__ "MatGetInfo_IS"
187fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
197fa8f2d3SStefano Zampini {
207fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
217fa8f2d3SStefano Zampini   MatInfo        info;
22314ce898Sstefano_zampini   PetscReal      isend[6],irecv[6];
237fa8f2d3SStefano Zampini   PetscInt       bs;
247fa8f2d3SStefano Zampini   PetscErrorCode ierr;
257fa8f2d3SStefano Zampini 
267fa8f2d3SStefano Zampini   PetscFunctionBegin;
277fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
28a2ccb5f9Sstefano_zampini   if (matis->A->ops->getinfo) {
297fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
307fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
317fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
327fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
337fa8f2d3SStefano Zampini     isend[3] = info.memory;
347fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
35a2ccb5f9Sstefano_zampini   } else {
36a2ccb5f9Sstefano_zampini     isend[0] = 0.;
37a2ccb5f9Sstefano_zampini     isend[1] = 0.;
38a2ccb5f9Sstefano_zampini     isend[2] = 0.;
39a2ccb5f9Sstefano_zampini     isend[3] = 0.;
40a2ccb5f9Sstefano_zampini     isend[4] = 0.;
41a2ccb5f9Sstefano_zampini   }
42314ce898Sstefano_zampini   isend[5] = matis->A->num_ass;
437fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
447fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
457fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
467fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
477fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
487fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
49314ce898Sstefano_zampini     ginfo->assemblies   = isend[5];
507fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
51314ce898Sstefano_zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
527fa8f2d3SStefano Zampini 
537fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
547fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
557fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
567fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
577fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
58314ce898Sstefano_zampini     ginfo->assemblies   = irecv[5];
597fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
607fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
617fa8f2d3SStefano Zampini 
627fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
637fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
647fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
657fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
667fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
677fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
687fa8f2d3SStefano Zampini   }
697fa8f2d3SStefano Zampini   ginfo->block_size        = bs;
707fa8f2d3SStefano Zampini   ginfo->fill_ratio_given  = 0;
717fa8f2d3SStefano Zampini   ginfo->fill_ratio_needed = 0;
727fa8f2d3SStefano Zampini   ginfo->factor_mallocs    = 0;
737fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
747fa8f2d3SStefano Zampini }
757fa8f2d3SStefano Zampini 
767fa8f2d3SStefano Zampini #undef __FUNCT__
775e3038f0Sstefano_zampini #define __FUNCT__ "MatConvert_Nest_IS"
785e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
795e3038f0Sstefano_zampini {
805e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
815e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
825e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
835e3038f0Sstefano_zampini   MPI_Comm               comm;
845e3038f0Sstefano_zampini   PetscInt               *lr,*lc,*lrb,*lcb,*l2gidxs;
855e3038f0Sstefano_zampini   PetscInt               sti,stl,i,j,nr,nc,rbs,cbs;
86*9e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
875e3038f0Sstefano_zampini   PetscErrorCode         ierr;
885e3038f0Sstefano_zampini 
895e3038f0Sstefano_zampini   PetscFunctionBeginUser;
905e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
915e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
925e3038f0Sstefano_zampini   rnest  = NULL;
935e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
945e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
955e3038f0Sstefano_zampini 
965e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
975e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
985e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
995e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
1005e3038f0Sstefano_zampini     if (isnest) {
1015e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
1025e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
1035e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
1045e3038f0Sstefano_zampini     }
1055e3038f0Sstefano_zampini   }
1065e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1075e3038f0Sstefano_zampini   ierr = PetscCalloc4(nr,&lr,nc,&lc,nr,&lrb,nc,&lcb);CHKERRQ(ierr);
108*9e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
1095e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
110*9e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
1115e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
1125e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
1135e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
1145e3038f0Sstefano_zampini       PetscBool ismatis;
115*9e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
1165e3038f0Sstefano_zampini 
1175e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
1185e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
1195e3038f0Sstefano_zampini 
1205e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
121*9e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
122*9e7b2b25Sstefano_zampini       if (istrans[ij]) {
123*9e7b2b25Sstefano_zampini         Mat T,lT;
124*9e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
125*9e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
126*9e7b2b25Sstefano_zampini         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) (transposed) is not of type MATIS",i,j);
127*9e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
128*9e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
129*9e7b2b25Sstefano_zampini       } else {
1305e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
1315e3038f0Sstefano_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);
132*9e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
133*9e7b2b25Sstefano_zampini       }
1345e3038f0Sstefano_zampini 
1355e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
1365e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
137*9e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
1385e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
1395e3038f0Sstefano_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);
1405e3038f0Sstefano_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);
1415e3038f0Sstefano_zampini       lr[i] = l1;
1425e3038f0Sstefano_zampini       lc[j] = l2;
143*9e7b2b25Sstefano_zampini       if (lrb[i] && lb1 != 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],lb1);
144*9e7b2b25Sstefano_zampini       if (lcb[j] && lb2 != 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],lb2);
145*9e7b2b25Sstefano_zampini       lrb[i] = lb1;
146*9e7b2b25Sstefano_zampini       lcb[j] = lb2;
1475e3038f0Sstefano_zampini 
1485e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
1495e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
1505e3038f0Sstefano_zampini     }
1515e3038f0Sstefano_zampini   }
1525e3038f0Sstefano_zampini 
1535e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
1545e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
1555e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
1565e3038f0Sstefano_zampini     rl2g = NULL;
1575e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
1585e3038f0Sstefano_zampini       PetscInt n1,n2;
1595e3038f0Sstefano_zampini 
1605e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
161*9e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
162*9e7b2b25Sstefano_zampini         Mat T;
163*9e7b2b25Sstefano_zampini 
164*9e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
165*9e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
166*9e7b2b25Sstefano_zampini       } else {
1675e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
168*9e7b2b25Sstefano_zampini       }
1695e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
1705e3038f0Sstefano_zampini       if (!n1) continue;
1715e3038f0Sstefano_zampini       if (!rl2g) {
1725e3038f0Sstefano_zampini         rl2g = cl2g;
1735e3038f0Sstefano_zampini       } else {
1745e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
1755e3038f0Sstefano_zampini         PetscBool      same;
1765e3038f0Sstefano_zampini 
1775e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
1785e3038f0Sstefano_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);
1795e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
1805e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
1815e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
1825e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
1835e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
1845e3038f0Sstefano_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);
1855e3038f0Sstefano_zampini       }
1865e3038f0Sstefano_zampini     }
1875e3038f0Sstefano_zampini   }
1885e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
1895e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
1905e3038f0Sstefano_zampini     rl2g = NULL;
1915e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
1925e3038f0Sstefano_zampini       PetscInt n1,n2;
1935e3038f0Sstefano_zampini 
1945e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
195*9e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
196*9e7b2b25Sstefano_zampini         Mat T;
197*9e7b2b25Sstefano_zampini 
198*9e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
199*9e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
200*9e7b2b25Sstefano_zampini       } else {
2015e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
202*9e7b2b25Sstefano_zampini       }
2035e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2045e3038f0Sstefano_zampini       if (!n1) continue;
2055e3038f0Sstefano_zampini       if (!rl2g) {
2065e3038f0Sstefano_zampini         rl2g = cl2g;
2075e3038f0Sstefano_zampini       } else {
2085e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2095e3038f0Sstefano_zampini         PetscBool      same;
2105e3038f0Sstefano_zampini 
2115e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2125e3038f0Sstefano_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);
2135e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2145e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2155e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2165e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2175e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2185e3038f0Sstefano_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);
2195e3038f0Sstefano_zampini       }
2205e3038f0Sstefano_zampini     }
2215e3038f0Sstefano_zampini   }
2225e3038f0Sstefano_zampini #endif
2235e3038f0Sstefano_zampini 
2245e3038f0Sstefano_zampini   B = NULL;
2255e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
2265e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
2275e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
2285e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
2295e3038f0Sstefano_zampini     for (i=0,sti=0,stl=0;i<nr;i++) {
2305e3038f0Sstefano_zampini       Mat            usedmat;
2315e3038f0Sstefano_zampini       Mat_IS         *matis;
2325e3038f0Sstefano_zampini       const PetscInt *idxs;
2335e3038f0Sstefano_zampini       PetscInt       n = lr[i]/lrb[i];
2345e3038f0Sstefano_zampini 
2355e3038f0Sstefano_zampini       /* local IS for local NEST */
2365e3038f0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr);
2375e3038f0Sstefano_zampini       sti  += n;
2385e3038f0Sstefano_zampini 
2395e3038f0Sstefano_zampini       /* l2gmap */
2405e3038f0Sstefano_zampini       j = 0;
2415e3038f0Sstefano_zampini       usedmat = nest[i][j];
242*9e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
243*9e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
244*9e7b2b25Sstefano_zampini 
245*9e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
246*9e7b2b25Sstefano_zampini         Mat T;
247*9e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
248*9e7b2b25Sstefano_zampini         usedmat = T;
249*9e7b2b25Sstefano_zampini       }
2505e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
2515e3038f0Sstefano_zampini       if (!matis->sf) {
2525e3038f0Sstefano_zampini         ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr);
2535e3038f0Sstefano_zampini       }
2545e3038f0Sstefano_zampini       ierr = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
255*9e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
256*9e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
257*9e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
258*9e7b2b25Sstefano_zampini       } else {
2595e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
2605e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
261*9e7b2b25Sstefano_zampini       }
2625e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
2635e3038f0Sstefano_zampini       stl += lr[i];
2645e3038f0Sstefano_zampini     }
2655e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
2665e3038f0Sstefano_zampini 
2675e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
2685e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
2695e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
2705e3038f0Sstefano_zampini     for (i=0,sti=0,stl=0;i<nc;i++) {
2715e3038f0Sstefano_zampini       Mat            usedmat;
2725e3038f0Sstefano_zampini       Mat_IS         *matis;
2735e3038f0Sstefano_zampini       const PetscInt *idxs;
2745e3038f0Sstefano_zampini       PetscInt       n = lc[i]/lcb[i];
2755e3038f0Sstefano_zampini 
2765e3038f0Sstefano_zampini       /* local IS for local NEST */
2775e3038f0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr);
2785e3038f0Sstefano_zampini       sti  += n;
2795e3038f0Sstefano_zampini 
2805e3038f0Sstefano_zampini       /* l2gmap */
2815e3038f0Sstefano_zampini       j = 0;
2825e3038f0Sstefano_zampini       usedmat = nest[j][i];
283*9e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
284*9e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
285*9e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
286*9e7b2b25Sstefano_zampini         Mat T;
287*9e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
288*9e7b2b25Sstefano_zampini         usedmat = T;
289*9e7b2b25Sstefano_zampini       }
2905e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
2915e3038f0Sstefano_zampini       if (!matis->sf) {
2925e3038f0Sstefano_zampini         ierr = MatISComputeSF_Private(usedmat);CHKERRQ(ierr);
2935e3038f0Sstefano_zampini       }
2945e3038f0Sstefano_zampini       ierr = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
295*9e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
296*9e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
297*9e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
298*9e7b2b25Sstefano_zampini       } else {
2995e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3005e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
301*9e7b2b25Sstefano_zampini       }
3025e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
3035e3038f0Sstefano_zampini       stl += lc[i];
3045e3038f0Sstefano_zampini     }
3055e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
3065e3038f0Sstefano_zampini 
3075e3038f0Sstefano_zampini     /* Create MATIS */
3085e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
3095e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
3105e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
3115e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
3125e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
3135e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
3145e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3155e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3165e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
317*9e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
318*9e7b2b25Sstefano_zampini       if (istrans[i]) {
319*9e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
320*9e7b2b25Sstefano_zampini       }
321*9e7b2b25Sstefano_zampini     }
3225e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
3235e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
3245e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3255e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3265e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
3275e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
3285e3038f0Sstefano_zampini     } else {
3295e3038f0Sstefano_zampini       *newmat = B;
3305e3038f0Sstefano_zampini     }
3315e3038f0Sstefano_zampini   } else {
3325e3038f0Sstefano_zampini     if (lreuse) {
3335e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
3345e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
3355e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
3365e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
3375e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
338*9e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
339*9e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
340*9e7b2b25Sstefano_zampini             }
3415e3038f0Sstefano_zampini           }
3425e3038f0Sstefano_zampini         }
3435e3038f0Sstefano_zampini       }
3445e3038f0Sstefano_zampini     } else {
3455e3038f0Sstefano_zampini       for (i=0,sti=0;i<nr;i++) {
3465e3038f0Sstefano_zampini         PetscInt n = lr[i]/lrb[i];
3475e3038f0Sstefano_zampini 
3485e3038f0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr);
3495e3038f0Sstefano_zampini         sti  += n;
3505e3038f0Sstefano_zampini       }
3515e3038f0Sstefano_zampini       for (i=0,sti=0;i<nc;i++) {
3525e3038f0Sstefano_zampini         PetscInt n = lc[i]/lcb[i];
3535e3038f0Sstefano_zampini 
3545e3038f0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr);
3555e3038f0Sstefano_zampini         sti  += n;
3565e3038f0Sstefano_zampini       }
3575e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
358*9e7b2b25Sstefano_zampini       if (istrans[i]) {
359*9e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
360*9e7b2b25Sstefano_zampini       }
3615e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
3625e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
3635e3038f0Sstefano_zampini     }
3645e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3655e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3665e3038f0Sstefano_zampini   }
3675e3038f0Sstefano_zampini 
3685e3038f0Sstefano_zampini   /* Free workspace */
3695e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
3705e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
3715e3038f0Sstefano_zampini   }
3725e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
3735e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
3745e3038f0Sstefano_zampini   }
3755e3038f0Sstefano_zampini   ierr = PetscFree4(lr,lc,lrb,lcb);CHKERRQ(ierr);
376*9e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
3775e3038f0Sstefano_zampini 
3785e3038f0Sstefano_zampini   /* Create local matrix in MATNEST format */
3795e3038f0Sstefano_zampini   convert = PETSC_FALSE;
3805e3038f0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
3815e3038f0Sstefano_zampini   if (convert) {
3825e3038f0Sstefano_zampini     Mat M;
3835e3038f0Sstefano_zampini 
3845e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
3855e3038f0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
3865e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
3875e3038f0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
3885e3038f0Sstefano_zampini   }
3895e3038f0Sstefano_zampini   PetscFunctionReturn(0);
3905e3038f0Sstefano_zampini }
3915e3038f0Sstefano_zampini 
3925e3038f0Sstefano_zampini #undef __FUNCT__
393d7f69cd0SStefano Zampini #define __FUNCT__ "MatTranspose_IS"
394d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
395d7f69cd0SStefano Zampini {
396d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
397d7f69cd0SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
398d7f69cd0SStefano Zampini   PetscBool              notset = PETSC_FALSE,cong = PETSC_TRUE;
399d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
400d7f69cd0SStefano Zampini 
401d7f69cd0SStefano Zampini   PetscFunctionBegin;
402d7f69cd0SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
403d7f69cd0SStefano Zampini     PetscBool rcong,ccong;
404d7f69cd0SStefano Zampini 
405d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr);
406d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr);
407fa520230SStefano Zampini     cong = (PetscBool)(rcong || ccong);
408d7f69cd0SStefano Zampini   }
409d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) {
410d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
411d7f69cd0SStefano Zampini   } else {
412d7f69cd0SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,&notset);CHKERRQ(ierr);
413d7f69cd0SStefano Zampini     C = *B;
414d7f69cd0SStefano Zampini   }
415d7f69cd0SStefano Zampini 
416d7f69cd0SStefano Zampini   if (!notset) {
417d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
418d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
419d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
420d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
421d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
422d7f69cd0SStefano Zampini   }
423d7f69cd0SStefano Zampini 
424d7f69cd0SStefano Zampini   /* perform local transposition */
425d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
426d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
427d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
428d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
429d7f69cd0SStefano Zampini 
430d7f69cd0SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
431d7f69cd0SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
432d7f69cd0SStefano Zampini 
433d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
434d7f69cd0SStefano Zampini     if (!cong) {
435d7f69cd0SStefano Zampini       ierr = MatDestroy(B);CHKERRQ(ierr);
436d7f69cd0SStefano Zampini     }
437d7f69cd0SStefano Zampini     *B = C;
438d7f69cd0SStefano Zampini   } else {
439d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
440d7f69cd0SStefano Zampini   }
441d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
442d7f69cd0SStefano Zampini }
443d7f69cd0SStefano Zampini 
444d7f69cd0SStefano Zampini #undef __FUNCT__
4453fd1c9e7SStefano Zampini #define __FUNCT__ "MatDiagonalSet_IS"
4463fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
4473fd1c9e7SStefano Zampini {
4483fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
4493fd1c9e7SStefano Zampini   PetscErrorCode ierr;
4503fd1c9e7SStefano Zampini 
4513fd1c9e7SStefano Zampini   PetscFunctionBegin;
4523fd1c9e7SStefano Zampini   if (!D) { /* this code branch is used by MatShift_IS */
4533fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
4543fd1c9e7SStefano Zampini   } else {
4553fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4563fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4573fd1c9e7SStefano Zampini   }
4583fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
4593fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
4603fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
4613fd1c9e7SStefano Zampini }
4623fd1c9e7SStefano Zampini 
4633fd1c9e7SStefano Zampini #undef __FUNCT__
4643fd1c9e7SStefano Zampini #define __FUNCT__ "MatShift_IS"
4653fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
4663fd1c9e7SStefano Zampini {
4673fd1c9e7SStefano Zampini   PetscErrorCode ierr;
4683fd1c9e7SStefano Zampini 
4693fd1c9e7SStefano Zampini   PetscFunctionBegin;
4703fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
4713fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
4723fd1c9e7SStefano Zampini }
4733fd1c9e7SStefano Zampini 
4743fd1c9e7SStefano Zampini #undef __FUNCT__
475f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS"
476f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
477f26d0771SStefano Zampini {
478f26d0771SStefano Zampini   PetscErrorCode ierr;
479f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
480f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
481f26d0771SStefano Zampini 
482f26d0771SStefano Zampini   PetscFunctionBegin;
483f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
484f26d0771SStefano 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);
485f26d0771SStefano Zampini #endif
486f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
487f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
488f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
489f26d0771SStefano Zampini   PetscFunctionReturn(0);
490f26d0771SStefano Zampini }
491f26d0771SStefano Zampini 
492f26d0771SStefano Zampini #undef __FUNCT__
493f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS"
494f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
495f26d0771SStefano Zampini {
496f26d0771SStefano Zampini   PetscErrorCode ierr;
497f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
498f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
499f26d0771SStefano Zampini 
500f26d0771SStefano Zampini   PetscFunctionBegin;
501f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
502f26d0771SStefano 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);
503f26d0771SStefano Zampini #endif
504f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
505f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
506f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
507f26d0771SStefano Zampini   PetscFunctionReturn(0);
508f26d0771SStefano Zampini }
509f26d0771SStefano Zampini 
510f26d0771SStefano Zampini #undef __FUNCT__
511a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private"
512f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
513a8116848SStefano Zampini {
514a8116848SStefano Zampini   PetscInt      *owners = map->range;
515a8116848SStefano Zampini   PetscInt       n      = map->n;
516a8116848SStefano Zampini   PetscSF        sf;
517a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
518a8116848SStefano Zampini   PetscSFNode   *ridxs;
519a8116848SStefano Zampini   PetscMPIInt    rank;
520a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
521a8116848SStefano Zampini   PetscErrorCode ierr;
522a8116848SStefano Zampini 
523a8116848SStefano Zampini   PetscFunctionBegin;
524fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
525a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
526a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
527a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
528a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
529a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
530a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
531a8116848SStefano Zampini     const PetscInt idx = idxs[r];
532a8116848SStefano 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);
533a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
534a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
535a8116848SStefano Zampini     }
536a8116848SStefano Zampini     ridxs[r].rank = p;
537a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
538a8116848SStefano Zampini   }
539a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
540a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
541a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
542a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
543f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
544a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
545f0ae7da4SStefano Zampini 
546f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
547a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
548a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
549a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
550a8116848SStefano Zampini     start -= cum;
551a8116848SStefano Zampini     cum = 0;
552a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
553a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
554a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
555a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
556a8116848SStefano Zampini   }
557a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
558a8116848SStefano Zampini   /* Compress and put in indices */
559a8116848SStefano Zampini   for (r = 0; r < n; ++r)
560a8116848SStefano Zampini     if (lidxs[r] >= 0) {
561a8116848SStefano Zampini       if (work) work[len] = work[r];
562a8116848SStefano Zampini       lidxs[len++] = r;
563a8116848SStefano Zampini     }
564a8116848SStefano Zampini   if (on) *on = len;
565a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
566a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
567a8116848SStefano Zampini   PetscFunctionReturn(0);
568a8116848SStefano Zampini }
569a8116848SStefano Zampini 
570a8116848SStefano Zampini #undef __FUNCT__
571a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS"
572a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
573a8116848SStefano Zampini {
574a8116848SStefano Zampini   Mat               locmat,newlocmat;
575a8116848SStefano Zampini   Mat_IS            *newmatis;
576a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
577a8116848SStefano Zampini   Vec               rtest,ltest;
578a8116848SStefano Zampini   const PetscScalar *array;
579a8116848SStefano Zampini #endif
580a8116848SStefano Zampini   const PetscInt    *idxs;
581a8116848SStefano Zampini   PetscInt          i,m,n;
582a8116848SStefano Zampini   PetscErrorCode    ierr;
583a8116848SStefano Zampini 
584a8116848SStefano Zampini   PetscFunctionBegin;
585a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
586a8116848SStefano Zampini     PetscBool ismatis;
587a8116848SStefano Zampini 
588a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
589a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
590a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
591a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
592a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
593a8116848SStefano Zampini   }
594a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
595a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
596a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
597a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
598a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
599a8116848SStefano Zampini   for (i=0;i<n;i++) {
600a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
601a8116848SStefano Zampini   }
602a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
603a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
604a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
605a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
606a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
607fd479f66SMatthew 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]));
608a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
609a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
610a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
611a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
612a8116848SStefano Zampini   for (i=0;i<n;i++) {
613a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
614a8116848SStefano Zampini   }
615a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
616a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
617a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
618a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
619a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
620fd479f66SMatthew 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]));
621a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
622a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
623a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
624a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
625a8116848SStefano Zampini #endif
626a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
627a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
628a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
629a8116848SStefano Zampini     IS                     is;
630a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
6316dd40735SStefano Zampini     PetscInt               ll,newloc;
632a8116848SStefano Zampini     MPI_Comm               comm;
633a8116848SStefano Zampini 
634a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
635a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
636a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
637a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
638a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
639a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
640a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
641a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
642f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
643a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
644a8116848SStefano Zampini     if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
645a8116848SStefano Zampini       ierr = MatISComputeSF_Private(mat);CHKERRQ(ierr);
646a8116848SStefano Zampini     }
647a8116848SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
648a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
649a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
650a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
651a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
652a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
653a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
654a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
655a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
656a8116848SStefano Zampini     for (i=0,newloc=0;i<matis->sf_nleaves;i++)
657a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
658a8116848SStefano Zampini         lidxs[newloc] = i;
659a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
660a8116848SStefano Zampini       }
661a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
662a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
663a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
664a8116848SStefano Zampini     /* local is to extract local submatrix */
665a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
666a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
667a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
668a8116848SStefano Zampini       PetscBool cong;
669a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
670a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
671a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
672a8116848SStefano Zampini     }
673a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
674a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
675a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
676a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
677a8116848SStefano Zampini     } else {
678a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
679a8116848SStefano Zampini 
680a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
681a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
682f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
683a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
684a8116848SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf_nroots*sizeof(PetscInt));CHKERRQ(ierr);
685a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
686a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
687a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
688a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
689a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
690a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
691a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
692a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
693a8116848SStefano Zampini       for (i=0,newloc=0;i<matis->csf_nleaves;i++)
694a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
695a8116848SStefano Zampini           lidxs[newloc] = i;
696a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
697a8116848SStefano Zampini         }
698a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
699a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
700a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
701a8116848SStefano Zampini       /* local is to extract local submatrix */
702a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
703a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
704a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
705a8116848SStefano Zampini     }
706a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
707a8116848SStefano Zampini   } else {
708a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
709a8116848SStefano Zampini   }
710a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
711a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
712a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
713a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
714a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
715a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
716a8116848SStefano Zampini   }
717a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
718a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
719a8116848SStefano Zampini   PetscFunctionReturn(0);
720a8116848SStefano Zampini }
721a8116848SStefano Zampini 
722a8116848SStefano Zampini #undef __FUNCT__
7232b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS"
724a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
7252b404112SStefano Zampini {
7262b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
7272b404112SStefano Zampini   PetscBool      ismatis;
7282b404112SStefano Zampini   PetscErrorCode ierr;
7292b404112SStefano Zampini 
7302b404112SStefano Zampini   PetscFunctionBegin;
7312b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
7322b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
7332b404112SStefano Zampini   b = (Mat_IS*)B->data;
7342b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
7352b404112SStefano Zampini   PetscFunctionReturn(0);
7362b404112SStefano Zampini }
7372b404112SStefano Zampini 
7382b404112SStefano Zampini #undef __FUNCT__
7396bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS"
740a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
7416bd84002SStefano Zampini {
742527b2640SStefano Zampini   Vec               v;
743527b2640SStefano Zampini   const PetscScalar *array;
744527b2640SStefano Zampini   PetscInt          i,n;
7456bd84002SStefano Zampini   PetscErrorCode    ierr;
7466bd84002SStefano Zampini 
7476bd84002SStefano Zampini   PetscFunctionBegin;
748527b2640SStefano Zampini   *missing = PETSC_FALSE;
749527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
750527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
751527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
752527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
753527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
754527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
755527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
756527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
757527b2640SStefano Zampini   if (d) {
758527b2640SStefano Zampini     *d = -1;
759527b2640SStefano Zampini     if (*missing) {
760527b2640SStefano Zampini       PetscInt rstart;
761527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
762527b2640SStefano Zampini       *d = i+rstart;
763527b2640SStefano Zampini     }
764527b2640SStefano Zampini   }
7656bd84002SStefano Zampini   PetscFunctionReturn(0);
7666bd84002SStefano Zampini }
7676bd84002SStefano Zampini 
7686bd84002SStefano Zampini #undef __FUNCT__
76928f4e0baSStefano Zampini #define __FUNCT__ "MatISComputeSF_Private"
770a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat B)
77128f4e0baSStefano Zampini {
77228f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
77328f4e0baSStefano Zampini   const PetscInt *gidxs;
77428f4e0baSStefano Zampini   PetscErrorCode ierr;
77528f4e0baSStefano Zampini 
77628f4e0baSStefano Zampini   PetscFunctionBegin;
77728f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,&matis->sf_nleaves,NULL);CHKERRQ(ierr);
77828f4e0baSStefano Zampini   ierr = MatGetLocalSize(B,&matis->sf_nroots,NULL);CHKERRQ(ierr);
77928f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
7803bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
78128f4e0baSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,matis->sf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
7823bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
78328f4e0baSStefano Zampini   ierr = PetscMalloc2(matis->sf_nroots,&matis->sf_rootdata,matis->sf_nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
784a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
785a8116848SStefano Zampini     ierr = MatGetSize(matis->A,NULL,&matis->csf_nleaves);CHKERRQ(ierr);
786a8116848SStefano Zampini     ierr = MatGetLocalSize(B,NULL,&matis->csf_nroots);CHKERRQ(ierr);
787a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
788a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
789a8116848SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,matis->csf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
790a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
791a8116848SStefano Zampini     ierr = PetscMalloc2(matis->csf_nroots,&matis->csf_rootdata,matis->csf_nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
792a8116848SStefano Zampini   } else {
793a8116848SStefano Zampini     matis->csf = matis->sf;
794a8116848SStefano Zampini     matis->csf_nleaves = matis->sf_nleaves;
795a8116848SStefano Zampini     matis->csf_nroots = matis->sf_nroots;
796a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
797a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
798a8116848SStefano Zampini   }
79928f4e0baSStefano Zampini   PetscFunctionReturn(0);
80028f4e0baSStefano Zampini }
8012e1947a5SStefano Zampini 
8022e1947a5SStefano Zampini #undef __FUNCT__
8032e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
804eb82efa4SStefano Zampini /*@
805a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
806a88811baSStefano Zampini 
807a88811baSStefano Zampini    Collective on MPI_Comm
808a88811baSStefano Zampini 
809a88811baSStefano Zampini    Input Parameters:
810a88811baSStefano Zampini +  B - the matrix
811a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
812a88811baSStefano Zampini            (same value is used for all local rows)
813a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
814a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
815a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
816a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
817a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
818a88811baSStefano Zampini            the diagonal entry even if it is zero.
819a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
820a88811baSStefano Zampini            submatrix (same value is used for all local rows).
821a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
822a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
823a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
824a88811baSStefano Zampini            structure. The size of this array is equal to the number
825a88811baSStefano Zampini            of local rows, i.e 'm'.
826a88811baSStefano Zampini 
827a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
828a88811baSStefano Zampini 
829a88811baSStefano Zampini    Level: intermediate
830a88811baSStefano Zampini 
831a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
832a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
833a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
834a88811baSStefano Zampini 
835a88811baSStefano Zampini .keywords: matrix
836a88811baSStefano Zampini 
8373c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
838a88811baSStefano Zampini @*/
8392e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
8402e1947a5SStefano Zampini {
8412e1947a5SStefano Zampini   PetscErrorCode ierr;
8422e1947a5SStefano Zampini 
8432e1947a5SStefano Zampini   PetscFunctionBegin;
8442e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
8452e1947a5SStefano Zampini   PetscValidType(B,1);
8462e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
8472e1947a5SStefano Zampini   PetscFunctionReturn(0);
8482e1947a5SStefano Zampini }
8492e1947a5SStefano Zampini 
8502e1947a5SStefano Zampini #undef __FUNCT__
8512e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
8527230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
8532e1947a5SStefano Zampini {
8542e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
85528f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
8562e1947a5SStefano Zampini   PetscErrorCode ierr;
8572e1947a5SStefano Zampini 
8582e1947a5SStefano Zampini   PetscFunctionBegin;
8596c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
86028f4e0baSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
86128f4e0baSStefano Zampini     ierr = MatISComputeSF_Private(B);CHKERRQ(ierr);
86228f4e0baSStefano Zampini   }
8632e1947a5SStefano Zampini   if (!d_nnz) {
86428f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nz;
8652e1947a5SStefano Zampini   } else {
86628f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
8672e1947a5SStefano Zampini   }
8682e1947a5SStefano Zampini   if (!o_nnz) {
86928f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nz;
8702e1947a5SStefano Zampini   } else {
87128f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
8722e1947a5SStefano Zampini   }
87328f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
87428f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
87528f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
87628f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
87728f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves;i++) {
87828f4e0baSStefano Zampini     matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
8792e1947a5SStefano Zampini   }
88028f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
88128f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
88228f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
8832e1947a5SStefano Zampini   }
88428f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
88528f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
88628f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
8872e1947a5SStefano Zampini   }
88828f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
8892e1947a5SStefano Zampini   PetscFunctionReturn(0);
8902e1947a5SStefano Zampini }
891b4319ba4SBarry Smith 
892b4319ba4SBarry Smith #undef __FUNCT__
8933927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
8943927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
8953927de2eSStefano Zampini {
8963927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
8973927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
898ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
8993927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
9003927de2eSStefano Zampini   PetscInt        lrows,lcols;
9013927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
9023927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
9033927de2eSStefano Zampini   PetscBool       isdense,issbaij;
9043927de2eSStefano Zampini   PetscErrorCode  ierr;
9053927de2eSStefano Zampini 
9063927de2eSStefano Zampini   PetscFunctionBegin;
9073927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
9083927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
9093927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
9103927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
9113927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
9123927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
913ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
914ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
9157230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
916ecf5a873SStefano Zampini   } else {
917ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
918ecf5a873SStefano Zampini   }
919ecf5a873SStefano Zampini 
9203927de2eSStefano Zampini   if (issbaij) {
9213927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
9223927de2eSStefano Zampini   }
9233927de2eSStefano Zampini   /*
924ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
9253927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
9263927de2eSStefano Zampini   */
9273927de2eSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
9283927de2eSStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
9293927de2eSStefano Zampini   }
9303927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
9313927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
9323927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
9333927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
9343927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
9353927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
9363927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
9373927de2eSStefano Zampini       row_ownership[j] = i;
9383927de2eSStefano Zampini     }
9393927de2eSStefano Zampini   }
9407230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
9413927de2eSStefano Zampini 
9423927de2eSStefano Zampini   /*
9433927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
9443927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
9453927de2eSStefano Zampini   */
9463927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
9473927de2eSStefano Zampini   /* preallocation as a MATAIJ */
9483927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
9493927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
950ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
9513927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
9523927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
953ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
9543927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
9553927de2eSStefano Zampini           my_dnz[i] += 1;
9563927de2eSStefano Zampini         } else { /* offdiag block */
9573927de2eSStefano Zampini           my_onz[i] += 1;
9583927de2eSStefano Zampini         }
9593927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
9603927de2eSStefano Zampini         if (i != j) {
9613927de2eSStefano Zampini           owner = row_ownership[index_col];
9623927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
9633927de2eSStefano Zampini             my_dnz[j] += 1;
9643927de2eSStefano Zampini           } else {
9653927de2eSStefano Zampini             my_onz[j] += 1;
9663927de2eSStefano Zampini           }
9673927de2eSStefano Zampini         }
9683927de2eSStefano Zampini       }
9693927de2eSStefano Zampini     }
970bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
971bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
972bb1015c3SStefano Zampini     PetscBool      done;
973bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
974bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
975bb1015c3SStefano Zampini     jptr = jj;
976bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
977bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
978bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
979bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
980bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
981bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
982bb1015c3SStefano Zampini           my_dnz[i] += 1;
983bb1015c3SStefano Zampini         } else { /* offdiag block */
984bb1015c3SStefano Zampini           my_onz[i] += 1;
985bb1015c3SStefano Zampini         }
986bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
987bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
988bb1015c3SStefano Zampini           owner = row_ownership[index_col];
989bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
990bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
991bb1015c3SStefano Zampini           } else {
992bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
993bb1015c3SStefano Zampini           }
994bb1015c3SStefano Zampini         }
995bb1015c3SStefano Zampini       }
996bb1015c3SStefano Zampini     }
997bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
998bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
999bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
10003927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
10013927de2eSStefano Zampini       const PetscInt *cols;
1002ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
10033927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
10043927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
10053927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1006ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
10073927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
10083927de2eSStefano Zampini           my_dnz[i] += 1;
10093927de2eSStefano Zampini         } else { /* offdiag block */
10103927de2eSStefano Zampini           my_onz[i] += 1;
10113927de2eSStefano Zampini         }
10123927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1013d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
10143927de2eSStefano Zampini           owner = row_ownership[index_col];
10153927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1016d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
10173927de2eSStefano Zampini           } else {
1018d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
10193927de2eSStefano Zampini           }
10203927de2eSStefano Zampini         }
10213927de2eSStefano Zampini       }
10223927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
10233927de2eSStefano Zampini     }
10243927de2eSStefano Zampini   }
1025ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1026ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
10277230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1028ecf5a873SStefano Zampini   }
10293927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1030ecf5a873SStefano Zampini 
1031ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
10323927de2eSStefano Zampini   if (maxreduce) {
10333927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
10343927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1035bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
10363927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
10373927de2eSStefano Zampini   } else {
10383927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
10393927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1040bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
10413927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
10423927de2eSStefano Zampini   }
10433927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
10443927de2eSStefano Zampini 
10453927de2eSStefano Zampini   /* Resize preallocation if overestimated */
10463927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
10473927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
10483927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
10493927de2eSStefano Zampini   }
10501670daf9Sstefano_zampini 
10511670daf9Sstefano_zampini   /* Set preallocation */
10523927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
10533927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
10543927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
10553927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
10563927de2eSStefano Zampini   }
10573927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
10583927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
10593927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
10603927de2eSStefano Zampini   if (issbaij) {
10613927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
10623927de2eSStefano Zampini   }
10633927de2eSStefano Zampini   PetscFunctionReturn(0);
10643927de2eSStefano Zampini }
10653927de2eSStefano Zampini 
10663927de2eSStefano Zampini #undef __FUNCT__
1067b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
10687230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1069b7ce53b6SStefano Zampini {
1070b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1071d9a9e74cSStefano Zampini   Mat            local_mat;
1072b7ce53b6SStefano Zampini   /* info on mat */
10733cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1074b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1075686e3a49SStefano Zampini   PetscBool      isdense,issbaij,isseqaij;
10767c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1077b7ce53b6SStefano Zampini   /* values insertion */
1078b7ce53b6SStefano Zampini   PetscScalar    *array;
1079b7ce53b6SStefano Zampini   /* work */
1080b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1081b7ce53b6SStefano Zampini 
1082b7ce53b6SStefano Zampini   PetscFunctionBegin;
1083b7ce53b6SStefano Zampini   /* get info from mat */
10847c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
10857c03b4e8SStefano Zampini   if (nsubdomains == 1) {
10861670daf9Sstefano_zampini     Mat            B;
10871670daf9Sstefano_zampini     IS             rows,cols;
10881670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
10891670daf9Sstefano_zampini 
10901670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
10911670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
10921670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
10931670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
10941670daf9Sstefano_zampini     ierr = MatConvert(matis->A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
10951670daf9Sstefano_zampini     ierr = MatGetSubMatrix(B,rows,cols,reuse,M);CHKERRQ(ierr);
10961670daf9Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
10971670daf9Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
10981670daf9Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
10991670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
11001670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
11017c03b4e8SStefano Zampini     PetscFunctionReturn(0);
11027c03b4e8SStefano Zampini   }
1103b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1104b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
11053cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1106b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1107b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
1108686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1109b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1110b7ce53b6SStefano Zampini 
1111b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
1112b7ce53b6SStefano Zampini     MatType     new_mat_type;
11133927de2eSStefano Zampini     PetscBool   issbaij_red;
1114b7ce53b6SStefano Zampini 
1115b7ce53b6SStefano Zampini     /* determining new matrix type */
1116b2566f29SBarry Smith     ierr = MPIU_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1117b7ce53b6SStefano Zampini     if (issbaij_red) {
1118b7ce53b6SStefano Zampini       new_mat_type = MATSBAIJ;
1119b7ce53b6SStefano Zampini     } else {
1120b7ce53b6SStefano Zampini       if (bs>1) {
1121b7ce53b6SStefano Zampini         new_mat_type = MATBAIJ;
1122b7ce53b6SStefano Zampini       } else {
1123b7ce53b6SStefano Zampini         new_mat_type = MATAIJ;
1124b7ce53b6SStefano Zampini       }
1125b7ce53b6SStefano Zampini     }
1126b7ce53b6SStefano Zampini 
11273927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
11283cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
11293927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
11303927de2eSStefano Zampini     ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr);
11313927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1132b7ce53b6SStefano Zampini   } else {
11333cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1134b7ce53b6SStefano Zampini     /* some checks */
1135b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1136b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
11373cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
11386c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
11396c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
11406c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
11416c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
11426c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1143b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1144b7ce53b6SStefano Zampini   }
1145d9a9e74cSStefano Zampini 
1146d9a9e74cSStefano Zampini   if (issbaij) {
1147d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1148d9a9e74cSStefano Zampini   } else {
1149d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1150d9a9e74cSStefano Zampini     local_mat = matis->A;
1151d9a9e74cSStefano Zampini   }
1152686e3a49SStefano Zampini 
1153b7ce53b6SStefano Zampini   /* Set values */
1154ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1155b7ce53b6SStefano Zampini   if (isdense) { /* special case for dense local matrices */
1156ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
1157ecf5a873SStefano Zampini 
1158ecf5a873SStefano Zampini     if (local_rows != local_cols) {
1159ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
1160ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1161ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
1162ecf5a873SStefano Zampini     } else {
1163ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
1164ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1165ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
1166ecf5a873SStefano Zampini     }
1167b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1168d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
1169ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
1170d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
1171ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
1172ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
1173ecf5a873SStefano Zampini     } else {
1174ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
1175ecf5a873SStefano Zampini     }
1176686e3a49SStefano Zampini   } else if (isseqaij) {
1177ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1178686e3a49SStefano Zampini     PetscBool done;
1179686e3a49SStefano Zampini 
1180d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1181bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1182d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1183686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1184ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1185686e3a49SStefano Zampini     }
1186d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1187bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1188d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1189686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1190ecf5a873SStefano Zampini     PetscInt i;
1191c0962df8SStefano Zampini 
1192686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1193686e3a49SStefano Zampini       PetscInt       j;
1194ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1195686e3a49SStefano Zampini 
1196ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1197ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1198ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1199686e3a49SStefano Zampini     }
1200b7ce53b6SStefano Zampini   }
1201b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1202d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1203b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1204b7ce53b6SStefano Zampini   if (isdense) {
1205b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1206b7ce53b6SStefano Zampini   }
1207b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1208b7ce53b6SStefano Zampini }
1209b7ce53b6SStefano Zampini 
1210b7ce53b6SStefano Zampini #undef __FUNCT__
1211b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
1212b7ce53b6SStefano Zampini /*@
1213b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1214b7ce53b6SStefano Zampini 
1215b7ce53b6SStefano Zampini   Input Parameter:
1216b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1217b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1218b7ce53b6SStefano Zampini 
1219b7ce53b6SStefano Zampini   Output Parameter:
1220b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1221b7ce53b6SStefano Zampini 
1222b7ce53b6SStefano Zampini   Level: developer
1223b7ce53b6SStefano Zampini 
1224eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1225b7ce53b6SStefano Zampini 
1226b7ce53b6SStefano Zampini .seealso: MATIS
1227b7ce53b6SStefano Zampini @*/
1228b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1229b7ce53b6SStefano Zampini {
1230b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1231b7ce53b6SStefano Zampini 
1232b7ce53b6SStefano Zampini   PetscFunctionBegin;
1233b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1234b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1235b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1236b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1237b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1238b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
12396c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1240b7ce53b6SStefano Zampini   }
1241b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1242b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1243b7ce53b6SStefano Zampini }
1244b7ce53b6SStefano Zampini 
1245b7ce53b6SStefano Zampini #undef __FUNCT__
1246ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
1247ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1248ad6194a2SStefano Zampini {
1249ad6194a2SStefano Zampini   PetscErrorCode ierr;
1250ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1251ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1252ad6194a2SStefano Zampini   Mat            B,localmat;
1253ad6194a2SStefano Zampini 
1254ad6194a2SStefano Zampini   PetscFunctionBegin;
1255ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1256ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1257ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1258e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1259ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1260ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1261b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1262ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1263ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1264ad6194a2SStefano Zampini   *newmat = B;
1265ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1266ad6194a2SStefano Zampini }
1267ad6194a2SStefano Zampini 
1268ad6194a2SStefano Zampini #undef __FUNCT__
126969796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
1270a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
127169796d55SStefano Zampini {
127269796d55SStefano Zampini   PetscErrorCode ierr;
127369796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
127469796d55SStefano Zampini   PetscBool      local_sym;
127569796d55SStefano Zampini 
127669796d55SStefano Zampini   PetscFunctionBegin;
127769796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1278b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
127969796d55SStefano Zampini   PetscFunctionReturn(0);
128069796d55SStefano Zampini }
128169796d55SStefano Zampini 
128269796d55SStefano Zampini #undef __FUNCT__
128369796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
1284a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
128569796d55SStefano Zampini {
128669796d55SStefano Zampini   PetscErrorCode ierr;
128769796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
128869796d55SStefano Zampini   PetscBool      local_sym;
128969796d55SStefano Zampini 
129069796d55SStefano Zampini   PetscFunctionBegin;
129169796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1292b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
129369796d55SStefano Zampini   PetscFunctionReturn(0);
129469796d55SStefano Zampini }
129569796d55SStefano Zampini 
129669796d55SStefano Zampini #undef __FUNCT__
1297b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
1298a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1299b4319ba4SBarry Smith {
1300dfbe8321SBarry Smith   PetscErrorCode ierr;
1301b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1302b4319ba4SBarry Smith 
1303b4319ba4SBarry Smith   PetscFunctionBegin;
13046bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1305e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1306e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
13076bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
13086bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
13093fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1310a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1311a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1312a8116848SStefano Zampini   if (b->sf != b->csf) {
1313a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1314a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1315a8116848SStefano Zampini   }
131628f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
131728f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1318bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1319dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1320bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1321b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1322b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
13232e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1324b4319ba4SBarry Smith   PetscFunctionReturn(0);
1325b4319ba4SBarry Smith }
1326b4319ba4SBarry Smith 
1327b4319ba4SBarry Smith #undef __FUNCT__
1328b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
1329a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1330b4319ba4SBarry Smith {
1331dfbe8321SBarry Smith   PetscErrorCode ierr;
1332b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1333b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1334b4319ba4SBarry Smith 
1335b4319ba4SBarry Smith   PetscFunctionBegin;
1336b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1337e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1338e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1339b4319ba4SBarry Smith 
1340b4319ba4SBarry Smith   /* multiply the local matrix */
1341b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1342b4319ba4SBarry Smith 
1343b4319ba4SBarry Smith   /* scatter product back into global memory */
13442dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1345e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1346e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1347b4319ba4SBarry Smith   PetscFunctionReturn(0);
1348b4319ba4SBarry Smith }
1349b4319ba4SBarry Smith 
1350b4319ba4SBarry Smith #undef __FUNCT__
13512e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
1352a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
13532e74eeadSLisandro Dalcin {
1354650997f4SStefano Zampini   Vec            temp_vec;
13552e74eeadSLisandro Dalcin   PetscErrorCode ierr;
13562e74eeadSLisandro Dalcin 
13572e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1358650997f4SStefano Zampini   if (v3 != v2) {
1359650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1360650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1361650997f4SStefano Zampini   } else {
1362650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1363650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1364650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1365650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1366650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1367650997f4SStefano Zampini   }
13682e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
13692e74eeadSLisandro Dalcin }
13702e74eeadSLisandro Dalcin 
13712e74eeadSLisandro Dalcin #undef __FUNCT__
13722e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
1373a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
13742e74eeadSLisandro Dalcin {
13752e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
13762e74eeadSLisandro Dalcin   PetscErrorCode ierr;
13772e74eeadSLisandro Dalcin 
1378e176bc59SStefano Zampini   PetscFunctionBegin;
13792e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1380e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1381e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13822e74eeadSLisandro Dalcin 
13832e74eeadSLisandro Dalcin   /* multiply the local matrix */
1384e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
13852e74eeadSLisandro Dalcin 
13862e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1387e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1388e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1389e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13902e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
13912e74eeadSLisandro Dalcin }
13922e74eeadSLisandro Dalcin 
13932e74eeadSLisandro Dalcin #undef __FUNCT__
13942e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
1395a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
13962e74eeadSLisandro Dalcin {
1397650997f4SStefano Zampini   Vec            temp_vec;
13982e74eeadSLisandro Dalcin   PetscErrorCode ierr;
13992e74eeadSLisandro Dalcin 
14002e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1401650997f4SStefano Zampini   if (v3 != v2) {
1402650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1403650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1404650997f4SStefano Zampini   } else {
1405650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1406650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1407650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1408650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1409650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1410650997f4SStefano Zampini   }
14112e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14122e74eeadSLisandro Dalcin }
14132e74eeadSLisandro Dalcin 
14142e74eeadSLisandro Dalcin #undef __FUNCT__
1415b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
1416a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1417b4319ba4SBarry Smith {
1418b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1419dfbe8321SBarry Smith   PetscErrorCode ierr;
1420b4319ba4SBarry Smith   PetscViewer    sviewer;
1421b4319ba4SBarry Smith 
1422b4319ba4SBarry Smith   PetscFunctionBegin;
14233f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1424b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
14253f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
14266e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1427b4319ba4SBarry Smith   PetscFunctionReturn(0);
1428b4319ba4SBarry Smith }
1429b4319ba4SBarry Smith 
1430b4319ba4SBarry Smith #undef __FUNCT__
1431b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
1432a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1433b4319ba4SBarry Smith {
1434dfbe8321SBarry Smith   PetscErrorCode ierr;
1435e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1436b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1437b4319ba4SBarry Smith   IS             from,to;
1438e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1439b4319ba4SBarry Smith 
1440b4319ba4SBarry Smith   PetscFunctionBegin;
1441784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1442e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
14433bbff08aSStefano Zampini   /* Destroy any previous data */
144470cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
144570cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
14463fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1447e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1448e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
14491c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
145028f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
145128f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
14523bbff08aSStefano Zampini 
14533bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1454fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1455fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1456fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1457fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1458b4319ba4SBarry Smith 
1459b4319ba4SBarry Smith   /* Create the local matrix A */
1460e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1461e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1462e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1463e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1464f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1465e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1466e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1467e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1468ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1469ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1470b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1471b4319ba4SBarry Smith 
1472f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1473b4319ba4SBarry Smith     /* Create the local work vectors */
14743bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1475b4319ba4SBarry Smith 
1476e176bc59SStefano Zampini     /* setup the global to local scatters */
1477e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1478e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1479784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1480e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1481e176bc59SStefano Zampini     if (rmapping != cmapping) {
1482e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1483e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1484e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1485e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1486e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1487e176bc59SStefano Zampini     } else {
1488e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1489e176bc59SStefano Zampini       is->cctx = is->rctx;
1490e176bc59SStefano Zampini     }
14913fd1c9e7SStefano Zampini 
14923fd1c9e7SStefano Zampini     /* interface counter vector (local) */
14933fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
14943fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
14953fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14963fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14973fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14983fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14993fd1c9e7SStefano Zampini 
15003fd1c9e7SStefano Zampini     /* free workspace */
1501e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1502e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
15036bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
15046bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1505f26d0771SStefano Zampini   }
150648ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1507b4319ba4SBarry Smith   PetscFunctionReturn(0);
1508b4319ba4SBarry Smith }
1509b4319ba4SBarry Smith 
15102e74eeadSLisandro Dalcin #undef __FUNCT__
15112e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
1512a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
15132e74eeadSLisandro Dalcin {
15142e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
15152e74eeadSLisandro Dalcin   PetscErrorCode ierr;
151697563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
151797563a80SStefano Zampini   PetscInt       i,zm,zn;
151897563a80SStefano Zampini #endif
1519f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
15202e74eeadSLisandro Dalcin 
15212e74eeadSLisandro Dalcin   PetscFunctionBegin;
15222e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1523f26d0771SStefano 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);
152497563a80SStefano Zampini   /* count negative indices */
152597563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
152697563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
15272e74eeadSLisandro Dalcin #endif
152897563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
152997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
153097563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
153197563a80SStefano Zampini   /* count negative indices (should be the same as before) */
153297563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
153397563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
153497563a80SStefano 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");
153597563a80SStefano 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");
153697563a80SStefano Zampini #endif
15372e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
15382e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15392e74eeadSLisandro Dalcin }
15402e74eeadSLisandro Dalcin 
1541b4319ba4SBarry Smith #undef __FUNCT__
154297563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS"
1543a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
154497563a80SStefano Zampini {
154597563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
154697563a80SStefano Zampini   PetscErrorCode ierr;
154797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
154897563a80SStefano Zampini   PetscInt       i,zm,zn;
154997563a80SStefano Zampini #endif
1550f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
155197563a80SStefano Zampini 
155297563a80SStefano Zampini   PetscFunctionBegin;
155397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1554f26d0771SStefano 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);
155597563a80SStefano Zampini   /* count negative indices */
155697563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
155797563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
155897563a80SStefano Zampini #endif
155997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
156097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
156197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
156297563a80SStefano Zampini   /* count negative indices (should be the same as before) */
156397563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
156497563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
156597563a80SStefano 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");
156697563a80SStefano 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");
156797563a80SStefano Zampini #endif
156897563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
156997563a80SStefano Zampini   PetscFunctionReturn(0);
157097563a80SStefano Zampini }
157197563a80SStefano Zampini 
157297563a80SStefano Zampini #undef __FUNCT__
1573b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
1574a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1575b4319ba4SBarry Smith {
1576dfbe8321SBarry Smith   PetscErrorCode ierr;
1577b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1578b4319ba4SBarry Smith 
1579b4319ba4SBarry Smith   PetscFunctionBegin;
1580b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1581b4319ba4SBarry Smith   PetscFunctionReturn(0);
1582b4319ba4SBarry Smith }
1583b4319ba4SBarry Smith 
1584b4319ba4SBarry Smith #undef __FUNCT__
1585f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
1586a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1587f0006bf2SLisandro Dalcin {
1588f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1589f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1590f0006bf2SLisandro Dalcin 
1591f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1592f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1593f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1594f0006bf2SLisandro Dalcin }
1595f0006bf2SLisandro Dalcin 
1596f0006bf2SLisandro Dalcin #undef __FUNCT__
1597f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private"
1598f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1599f0ae7da4SStefano Zampini {
1600f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1601f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1602f0ae7da4SStefano Zampini 
1603f0ae7da4SStefano Zampini   PetscFunctionBegin;
1604f0ae7da4SStefano Zampini   if (!n) {
1605f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1606f0ae7da4SStefano Zampini   } else {
1607f0ae7da4SStefano Zampini     PetscInt i;
1608f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1609f0ae7da4SStefano Zampini 
1610f0ae7da4SStefano Zampini     if (columns) {
1611f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1612f0ae7da4SStefano Zampini     } else {
1613f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1614f0ae7da4SStefano Zampini     }
1615f0ae7da4SStefano Zampini     if (diag != 0.) {
1616f0ae7da4SStefano Zampini       const PetscScalar *array;
1617f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1618f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1619f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1620f0ae7da4SStefano Zampini       }
1621f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1622f0ae7da4SStefano Zampini     }
1623f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1624f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1625f0ae7da4SStefano Zampini   }
1626f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1627f0ae7da4SStefano Zampini }
1628f0ae7da4SStefano Zampini 
1629f0ae7da4SStefano Zampini #undef __FUNCT__
1630f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS"
1631f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
16322e74eeadSLisandro Dalcin {
16336e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
16346e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
16356e520ac8SStefano Zampini   PetscInt       *lrows;
16362e74eeadSLisandro Dalcin   PetscErrorCode ierr;
16372e74eeadSLisandro Dalcin 
16382e74eeadSLisandro Dalcin   PetscFunctionBegin;
1639f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1640f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1641f0ae7da4SStefano Zampini     PetscBool cong;
1642f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1643f0ae7da4SStefano 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");
1644f0ae7da4SStefano 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");
1645f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1646f0ae7da4SStefano Zampini   }
1647f0ae7da4SStefano Zampini #endif
16486e520ac8SStefano Zampini   /* get locally owned rows */
1649f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
16506e520ac8SStefano Zampini   /* fix right hand side if needed */
16516e520ac8SStefano Zampini   if (x && b) {
16526e520ac8SStefano Zampini     const PetscScalar *xx;
16536e520ac8SStefano Zampini     PetscScalar       *bb;
16546e520ac8SStefano Zampini 
16556e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
16566e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
16576e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
16586e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
16596e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
16602e74eeadSLisandro Dalcin   }
16616e520ac8SStefano Zampini   /* get rows associated to the local matrices */
16626e520ac8SStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
16636e520ac8SStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
16646e520ac8SStefano Zampini   }
16656e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
16666e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
16676e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
16686e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
16696e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
16706e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
16716e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
16726e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
16736e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1674f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
16756e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
16762e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
16772e74eeadSLisandro Dalcin }
16782e74eeadSLisandro Dalcin 
16792e74eeadSLisandro Dalcin #undef __FUNCT__
1680f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS"
1681f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1682b4319ba4SBarry Smith {
1683dfbe8321SBarry Smith   PetscErrorCode ierr;
1684b4319ba4SBarry Smith 
1685b4319ba4SBarry Smith   PetscFunctionBegin;
1686f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1687f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1688f0ae7da4SStefano Zampini }
16892205254eSKarl Rupp 
1690f0ae7da4SStefano Zampini #undef __FUNCT__
1691f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS"
1692f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1693f0ae7da4SStefano Zampini {
1694f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1695f0ae7da4SStefano Zampini 
1696f0ae7da4SStefano Zampini   PetscFunctionBegin;
1697f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1698b4319ba4SBarry Smith   PetscFunctionReturn(0);
1699b4319ba4SBarry Smith }
1700b4319ba4SBarry Smith 
1701b4319ba4SBarry Smith #undef __FUNCT__
1702b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
1703a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1704b4319ba4SBarry Smith {
1705b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1706dfbe8321SBarry Smith   PetscErrorCode ierr;
1707b4319ba4SBarry Smith 
1708b4319ba4SBarry Smith   PetscFunctionBegin;
1709b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1710b4319ba4SBarry Smith   PetscFunctionReturn(0);
1711b4319ba4SBarry Smith }
1712b4319ba4SBarry Smith 
1713b4319ba4SBarry Smith #undef __FUNCT__
1714b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
1715a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1716b4319ba4SBarry Smith {
1717b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1718dfbe8321SBarry Smith   PetscErrorCode ierr;
1719b4319ba4SBarry Smith 
1720b4319ba4SBarry Smith   PetscFunctionBegin;
1721b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1722b4319ba4SBarry Smith   PetscFunctionReturn(0);
1723b4319ba4SBarry Smith }
1724b4319ba4SBarry Smith 
1725b4319ba4SBarry Smith #undef __FUNCT__
1726b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
1727a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1728b4319ba4SBarry Smith {
1729b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1730b4319ba4SBarry Smith 
1731b4319ba4SBarry Smith   PetscFunctionBegin;
1732b4319ba4SBarry Smith   *local = is->A;
1733b4319ba4SBarry Smith   PetscFunctionReturn(0);
1734b4319ba4SBarry Smith }
1735b4319ba4SBarry Smith 
1736b4319ba4SBarry Smith #undef __FUNCT__
1737b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
1738b4319ba4SBarry Smith /*@
1739b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1740b4319ba4SBarry Smith 
1741b4319ba4SBarry Smith   Input Parameter:
1742b4319ba4SBarry Smith .  mat - the matrix
1743b4319ba4SBarry Smith 
1744b4319ba4SBarry Smith   Output Parameter:
1745eb82efa4SStefano Zampini .  local - the local matrix
1746b4319ba4SBarry Smith 
1747b4319ba4SBarry Smith   Level: advanced
1748b4319ba4SBarry Smith 
1749b4319ba4SBarry Smith   Notes:
1750b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1751b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1752b4319ba4SBarry Smith   of the MatSetValues() operation.
1753b4319ba4SBarry Smith 
1754b4319ba4SBarry Smith .seealso: MATIS
1755b4319ba4SBarry Smith @*/
17567087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1757b4319ba4SBarry Smith {
17584ac538c5SBarry Smith   PetscErrorCode ierr;
1759b4319ba4SBarry Smith 
1760b4319ba4SBarry Smith   PetscFunctionBegin;
17610700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1762b4319ba4SBarry Smith   PetscValidPointer(local,2);
17634ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1764b4319ba4SBarry Smith   PetscFunctionReturn(0);
1765b4319ba4SBarry Smith }
1766b4319ba4SBarry Smith 
17673b03a366Sstefano_zampini #undef __FUNCT__
17683b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
1769a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
17703b03a366Sstefano_zampini {
17713b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
17723b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
17733b03a366Sstefano_zampini   PetscErrorCode ierr;
17743b03a366Sstefano_zampini 
17753b03a366Sstefano_zampini   PetscFunctionBegin;
17764e4c7dbeSStefano Zampini   if (is->A) {
17773b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
17783b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1779f0ae7da4SStefano 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);
17804e4c7dbeSStefano Zampini   }
17813b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
17823b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
17833b03a366Sstefano_zampini   is->A = local;
17843b03a366Sstefano_zampini   PetscFunctionReturn(0);
17853b03a366Sstefano_zampini }
17863b03a366Sstefano_zampini 
17873b03a366Sstefano_zampini #undef __FUNCT__
17883b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
17893b03a366Sstefano_zampini /*@
1790eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
17913b03a366Sstefano_zampini 
17923b03a366Sstefano_zampini   Input Parameter:
17933b03a366Sstefano_zampini .  mat - the matrix
1794eb82efa4SStefano Zampini .  local - the local matrix
17953b03a366Sstefano_zampini 
17963b03a366Sstefano_zampini   Output Parameter:
17973b03a366Sstefano_zampini 
17983b03a366Sstefano_zampini   Level: advanced
17993b03a366Sstefano_zampini 
18003b03a366Sstefano_zampini   Notes:
18013b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
18023b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
18033b03a366Sstefano_zampini 
18043b03a366Sstefano_zampini .seealso: MATIS
18053b03a366Sstefano_zampini @*/
18063b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
18073b03a366Sstefano_zampini {
18083b03a366Sstefano_zampini   PetscErrorCode ierr;
18093b03a366Sstefano_zampini 
18103b03a366Sstefano_zampini   PetscFunctionBegin;
18113b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1812b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
18133b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
18143b03a366Sstefano_zampini   PetscFunctionReturn(0);
18153b03a366Sstefano_zampini }
18163b03a366Sstefano_zampini 
18176726f965SBarry Smith #undef __FUNCT__
18186726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
1819a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
18206726f965SBarry Smith {
18216726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
18226726f965SBarry Smith   PetscErrorCode ierr;
18236726f965SBarry Smith 
18246726f965SBarry Smith   PetscFunctionBegin;
18256726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
18266726f965SBarry Smith   PetscFunctionReturn(0);
18276726f965SBarry Smith }
18286726f965SBarry Smith 
18296726f965SBarry Smith #undef __FUNCT__
18302e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
1831a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
18322e74eeadSLisandro Dalcin {
18332e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
18342e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18352e74eeadSLisandro Dalcin 
18362e74eeadSLisandro Dalcin   PetscFunctionBegin;
18372e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
18382e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18392e74eeadSLisandro Dalcin }
18402e74eeadSLisandro Dalcin 
18412e74eeadSLisandro Dalcin #undef __FUNCT__
18422e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
1843a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
18442e74eeadSLisandro Dalcin {
18452e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
18462e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18472e74eeadSLisandro Dalcin 
18482e74eeadSLisandro Dalcin   PetscFunctionBegin;
18492e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
1850e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
18512e74eeadSLisandro Dalcin 
18522e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
18532e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
1854e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1855e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18562e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18572e74eeadSLisandro Dalcin }
18582e74eeadSLisandro Dalcin 
18592e74eeadSLisandro Dalcin #undef __FUNCT__
18606726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
1861a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
18626726f965SBarry Smith {
18636726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
18646726f965SBarry Smith   PetscErrorCode ierr;
18656726f965SBarry Smith 
18666726f965SBarry Smith   PetscFunctionBegin;
18674e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
18686726f965SBarry Smith   PetscFunctionReturn(0);
18696726f965SBarry Smith }
18706726f965SBarry Smith 
1871284134d9SBarry Smith #undef __FUNCT__
1872f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS"
1873f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
1874f26d0771SStefano Zampini {
1875f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
1876f26d0771SStefano Zampini   Mat_IS         *x;
1877f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1878f26d0771SStefano Zampini   PetscBool      ismatis;
1879f26d0771SStefano Zampini #endif
1880f26d0771SStefano Zampini   PetscErrorCode ierr;
1881f26d0771SStefano Zampini 
1882f26d0771SStefano Zampini   PetscFunctionBegin;
1883f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1884f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
1885f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
1886f26d0771SStefano Zampini #endif
1887f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
1888f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
1889f26d0771SStefano Zampini   PetscFunctionReturn(0);
1890f26d0771SStefano Zampini }
1891f26d0771SStefano Zampini 
1892f26d0771SStefano Zampini #undef __FUNCT__
1893f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS"
1894f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
1895f26d0771SStefano Zampini {
1896f26d0771SStefano Zampini   Mat                    lA;
1897f26d0771SStefano Zampini   Mat_IS                 *matis;
1898f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
1899f26d0771SStefano Zampini   IS                     is;
1900f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
1901f26d0771SStefano Zampini   PetscInt               nrg;
1902f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
1903f26d0771SStefano Zampini   PetscErrorCode         ierr;
1904f26d0771SStefano Zampini 
1905f26d0771SStefano Zampini   PetscFunctionBegin;
1906f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1907f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
1908f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
1909f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
1910f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1911f0ae7da4SStefano 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);
1912f26d0771SStefano Zampini #endif
1913f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
1914f26d0771SStefano Zampini   /* map from [0,nrl) to row */
1915f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
1916f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1917f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
1918f26d0771SStefano Zampini #else
1919f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
1920f26d0771SStefano Zampini #endif
1921f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
1922f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1923f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1924f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1925f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
1926f26d0771SStefano Zampini   /* compute new l2g map for columns */
1927f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
1928f26d0771SStefano Zampini     const PetscInt *cg,*cl;
1929f26d0771SStefano Zampini     PetscInt       ncg;
1930f26d0771SStefano Zampini     PetscInt       ncl;
1931f26d0771SStefano Zampini 
1932f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1933f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
1934f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
1935f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
1936f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1937f0ae7da4SStefano 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);
1938f26d0771SStefano Zampini #endif
1939f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
1940f26d0771SStefano Zampini     /* map from [0,ncl) to col */
1941f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
1942f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1943f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
1944f26d0771SStefano Zampini #else
1945f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
1946f26d0771SStefano Zampini #endif
1947f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
1948f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1949f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1950f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1951f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1952f26d0771SStefano Zampini   } else {
1953f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
1954f26d0771SStefano Zampini     cl2g = rl2g;
1955f26d0771SStefano Zampini   }
1956f26d0771SStefano Zampini   /* create the MATIS submatrix */
1957f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
1958f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
1959f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1960f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
1961b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
1962f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
1963f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
1964f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1965f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
1966f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
1967f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1968f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1969f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1970f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1971f26d0771SStefano Zampini   /* remove unsupported ops */
1972f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1973f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
1974f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
1975f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
1976f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
1977f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
1978f26d0771SStefano Zampini   PetscFunctionReturn(0);
1979f26d0771SStefano Zampini }
1980f26d0771SStefano Zampini 
1981f26d0771SStefano Zampini #undef __FUNCT__
1982284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
1983284134d9SBarry Smith /*@
19843c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
1985284134d9SBarry Smith        process but not across processes.
1986284134d9SBarry Smith 
1987284134d9SBarry Smith    Input Parameters:
1988284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
1989e176bc59SStefano Zampini .     bs      - block size of the matrix
1990df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
1991e176bc59SStefano Zampini .     rmap    - local to global map for rows
1992e176bc59SStefano Zampini -     cmap    - local to global map for cols
1993284134d9SBarry Smith 
1994284134d9SBarry Smith    Output Parameter:
1995284134d9SBarry Smith .    A - the resulting matrix
1996284134d9SBarry Smith 
19978e6c10adSSatish Balay    Level: advanced
19988e6c10adSSatish Balay 
19993c212e90SHong Zhang    Notes: See MATIS for more details.
20006fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
20016fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
20023c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2003284134d9SBarry Smith 
2004284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2005284134d9SBarry Smith @*/
2006e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2007284134d9SBarry Smith {
2008284134d9SBarry Smith   PetscErrorCode ierr;
2009284134d9SBarry Smith 
2010284134d9SBarry Smith   PetscFunctionBegin;
20116fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2012284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
20136fdf41d1SStefano Zampini   if (bs > 0) {
2014d3ee2243SStefano Zampini     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
20156fdf41d1SStefano Zampini   }
2016284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
2017284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2018e176bc59SStefano Zampini   if (rmap && cmap) {
2019e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2020e176bc59SStefano Zampini   } else if (!rmap) {
2021e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2022e176bc59SStefano Zampini   } else {
2023e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2024e176bc59SStefano Zampini   }
2025284134d9SBarry Smith   PetscFunctionReturn(0);
2026284134d9SBarry Smith }
2027284134d9SBarry Smith 
2028b4319ba4SBarry Smith /*MC
2029f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2030b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2031b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2032b4319ba4SBarry Smith    product is handled "implicitly".
2033b4319ba4SBarry Smith 
2034b4319ba4SBarry Smith    Operations Provided:
20356726f965SBarry Smith +  MatMult()
20362e74eeadSLisandro Dalcin .  MatMultAdd()
20372e74eeadSLisandro Dalcin .  MatMultTranspose()
20382e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
20396726f965SBarry Smith .  MatZeroEntries()
20406726f965SBarry Smith .  MatSetOption()
20412e74eeadSLisandro Dalcin .  MatZeroRows()
20422e74eeadSLisandro Dalcin .  MatSetValues()
204397563a80SStefano Zampini .  MatSetValuesBlocked()
20446726f965SBarry Smith .  MatSetValuesLocal()
204597563a80SStefano Zampini .  MatSetValuesBlockedLocal()
20462e74eeadSLisandro Dalcin .  MatScale()
20472e74eeadSLisandro Dalcin .  MatGetDiagonal()
20482b404112SStefano Zampini .  MatMissingDiagonal()
20492b404112SStefano Zampini .  MatDuplicate()
20502b404112SStefano Zampini .  MatCopy()
2051f26d0771SStefano Zampini .  MatAXPY()
2052f26d0771SStefano Zampini .  MatGetSubMatrix()
2053f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2054d7f69cd0SStefano Zampini .  MatTranspose()
20556726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2056b4319ba4SBarry Smith 
2057b4319ba4SBarry Smith    Options Database Keys:
2058b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2059b4319ba4SBarry Smith 
2060b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
2061b4319ba4SBarry Smith 
2062b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2063b4319ba4SBarry Smith 
2064b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2065eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2066b4319ba4SBarry Smith 
2067b4319ba4SBarry Smith   Level: advanced
2068b4319ba4SBarry Smith 
2069f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2070b4319ba4SBarry Smith 
2071b4319ba4SBarry Smith M*/
2072b4319ba4SBarry Smith 
2073b4319ba4SBarry Smith #undef __FUNCT__
2074b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
20758cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2076b4319ba4SBarry Smith {
2077dfbe8321SBarry Smith   PetscErrorCode ierr;
2078b4319ba4SBarry Smith   Mat_IS         *b;
2079b4319ba4SBarry Smith 
2080b4319ba4SBarry Smith   PetscFunctionBegin;
2081b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2082b4319ba4SBarry Smith   A->data = (void*)b;
2083b4319ba4SBarry Smith 
2084e176bc59SStefano Zampini   /* matrix ops */
2085e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2086b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
20872e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
20882e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
20892e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2090b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2091b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
20922e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
209398921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2094b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2095f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
20962e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2097f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2098b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2099b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2100b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
21016726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
21022e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
21032e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
21046726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
210569796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
210669796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
2107ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
21086bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
21092b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2110659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
2111a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
2112f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
21133fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
21143fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2115d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
21167fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
2117b4319ba4SBarry Smith 
2118b7ce53b6SStefano Zampini   /* special MATIS functions */
2119bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
2120bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2121b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
21222e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
212317667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2124b4319ba4SBarry Smith   PetscFunctionReturn(0);
2125b4319ba4SBarry Smith }
2126