xref: /petsc/src/mat/impls/is/matis.c (revision 938e1ff88ec69b0ce7d479c29d585940f68f246a)
1b4319ba4SBarry Smith /*
2b4319ba4SBarry Smith     Creates a matrix class for using the Neumann-Neumann type preconditioners.
3b4319ba4SBarry Smith     This stores the matrices in globally unassembled form. Each processor
4b4319ba4SBarry Smith     assembles only its local Neumann problem and the parallel matrix vector
5b4319ba4SBarry Smith     product is handled "implicitly".
6b4319ba4SBarry Smith 
7b4319ba4SBarry Smith     Currently this allows for only one subdomain per processor.
8b4319ba4SBarry Smith */
9b4319ba4SBarry Smith 
10c6db04a5SJed Brown #include <../src/mat/impls/is/matis.h>      /*I "petscmat.h" I*/
116989cf23SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
124f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h>
1328f4e0baSStefano Zampini 
14f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
15f26d0771SStefano Zampini 
165b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
175b003df0Sstefano_zampini {
185b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
195b003df0Sstefano_zampini   PetscInt         i;
205b003df0Sstefano_zampini   PetscErrorCode   ierr;
215b003df0Sstefano_zampini 
225b003df0Sstefano_zampini   PetscFunctionBeginUser;
235b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
245b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
255b003df0Sstefano_zampini   }
265b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
275b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
285b003df0Sstefano_zampini   }
295b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
305b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
315b003df0Sstefano_zampini   PetscFunctionReturn(0);
325b003df0Sstefano_zampini }
33a72627d2SStefano Zampini 
345b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyArray_Private(void *ptr)
357fa8f2d3SStefano Zampini {
366989cf23SStefano Zampini   PetscErrorCode ierr;
376989cf23SStefano Zampini 
386989cf23SStefano Zampini   PetscFunctionBeginUser;
396989cf23SStefano Zampini   ierr = PetscFree(ptr);CHKERRQ(ierr);
406989cf23SStefano Zampini   PetscFunctionReturn(0);
416989cf23SStefano Zampini }
426989cf23SStefano Zampini 
436989cf23SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
446989cf23SStefano Zampini {
456989cf23SStefano Zampini   Mat_MPIAIJ             *aij  = (Mat_MPIAIJ*)A->data;
466989cf23SStefano Zampini   Mat_SeqAIJ             *diag = (Mat_SeqAIJ*)(aij->A->data);
476989cf23SStefano Zampini   Mat_SeqAIJ             *offd = (Mat_SeqAIJ*)(aij->B->data);
486989cf23SStefano Zampini   Mat                    lA;
496989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
506989cf23SStefano Zampini   IS                     is;
516989cf23SStefano Zampini   MPI_Comm               comm;
526989cf23SStefano Zampini   void                   *ptrs[2];
536989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
546989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
556989cf23SStefano Zampini   PetscInt               *di,*dj,*oi,*oj;
566989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
57e363d98aSStefano Zampini   PetscInt               lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
586989cf23SStefano Zampini   PetscErrorCode         ierr;
596989cf23SStefano Zampini 
606989cf23SStefano Zampini   PetscFunctionBeginUser;
616989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
626989cf23SStefano Zampini   if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present");
636989cf23SStefano Zampini 
646989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
656989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
666989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
676989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
686989cf23SStefano Zampini   di   = diag->i;
696989cf23SStefano Zampini   dj   = diag->j;
706989cf23SStefano Zampini   dd   = diag->a;
716989cf23SStefano Zampini   oc   = aij->B->cmap->n;
726989cf23SStefano Zampini   oi   = offd->i;
736989cf23SStefano Zampini   oj   = offd->j;
746989cf23SStefano Zampini   od   = offd->a;
756989cf23SStefano Zampini   nnz  = diag->i[dr] + offd->i[dr];
766989cf23SStefano Zampini 
776989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
786989cf23SStefano Zampini   ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
796989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
806989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
81e363d98aSStefano Zampini   if (dr) {
826989cf23SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
836989cf23SStefano Zampini     for (i=0; i<dc; i++) aux[i]    = i+stc;
846989cf23SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i];
856989cf23SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
86e363d98aSStefano Zampini     lc   = dc+oc;
87e363d98aSStefano Zampini   } else {
88e363d98aSStefano Zampini     ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
89e363d98aSStefano Zampini     lc   = 0;
90e363d98aSStefano Zampini   }
916989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
926989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
936989cf23SStefano Zampini 
946989cf23SStefano Zampini   /* create MATIS object */
956989cf23SStefano Zampini   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
966989cf23SStefano Zampini   ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
976989cf23SStefano Zampini   ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
986989cf23SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
996989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1006989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1016989cf23SStefano Zampini 
1026989cf23SStefano Zampini   /* merge local matrices */
1036989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
1046989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
1056989cf23SStefano Zampini   ii   = aux;
1066989cf23SStefano Zampini   jj   = aux+dr+1;
1076989cf23SStefano Zampini   aa   = data;
1086989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
1096989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
1106989cf23SStefano Zampini   {
1116989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
1126989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
1136989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
1146989cf23SStefano Zampini   }
1156989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
1166989cf23SStefano Zampini   ii   = aux;
1176989cf23SStefano Zampini   jj   = aux+dr+1;
1186989cf23SStefano Zampini   aa   = data;
119e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
1206989cf23SStefano Zampini 
1216989cf23SStefano Zampini   /* create containers to destroy the data */
1226989cf23SStefano Zampini   ptrs[0] = aux;
1236989cf23SStefano Zampini   ptrs[1] = data;
1246989cf23SStefano Zampini   for (i=0; i<2; i++) {
1256989cf23SStefano Zampini     PetscContainer c;
1266989cf23SStefano Zampini 
1276989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
1286989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
1295b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyArray_Private);CHKERRQ(ierr);
1306989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
1316989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
1326989cf23SStefano Zampini   }
1336989cf23SStefano Zampini 
1346989cf23SStefano Zampini   /* finalize matrix */
1356989cf23SStefano Zampini   ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
1366989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
1376989cf23SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1386989cf23SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1396989cf23SStefano Zampini   PetscFunctionReturn(0);
1406989cf23SStefano Zampini }
1416989cf23SStefano Zampini 
142cf0a3239SStefano Zampini /*@
1433d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
144cf0a3239SStefano Zampini 
145cf0a3239SStefano Zampini    Collective on MPI_Comm
146cf0a3239SStefano Zampini 
147cf0a3239SStefano Zampini    Input Parameters:
148cf0a3239SStefano Zampini +  A - the matrix
149cf0a3239SStefano Zampini 
150cf0a3239SStefano Zampini    Level: advanced
151cf0a3239SStefano Zampini 
1523d996552SStefano Zampini    Notes: This function does not need to be called by the user.
153cf0a3239SStefano Zampini 
154cf0a3239SStefano Zampini .keywords: matrix
155cf0a3239SStefano Zampini 
156cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
157cf0a3239SStefano Zampini @*/
158cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
159cf0a3239SStefano Zampini {
1607fa8f2d3SStefano Zampini   PetscErrorCode ierr;
1617fa8f2d3SStefano Zampini 
1627fa8f2d3SStefano Zampini   PetscFunctionBegin;
163cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
164cf0a3239SStefano Zampini   PetscValidType(A,1);
165cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
1667fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
1677fa8f2d3SStefano Zampini }
1687fa8f2d3SStefano Zampini 
1695e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1705e3038f0Sstefano_zampini {
1715e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
1725e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
1735e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
1745e3038f0Sstefano_zampini   MPI_Comm               comm;
1755b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
1765b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
1779e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
1785e3038f0Sstefano_zampini   PetscErrorCode         ierr;
1795e3038f0Sstefano_zampini 
1805e3038f0Sstefano_zampini   PetscFunctionBeginUser;
1815e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
1825e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
1835e3038f0Sstefano_zampini   rnest  = NULL;
1845e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
1855e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
1865e3038f0Sstefano_zampini 
1875e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1885e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
1895e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
1905e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
1915e3038f0Sstefano_zampini     if (isnest) {
1925e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
1935e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
1945e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
1955e3038f0Sstefano_zampini     }
1965e3038f0Sstefano_zampini   }
1975e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1985b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
1999e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
2005e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
2019e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
2025e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
2035e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2045e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2055e3038f0Sstefano_zampini       PetscBool ismatis;
2069e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
2075e3038f0Sstefano_zampini 
2085e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
2095e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2105e3038f0Sstefano_zampini 
2115e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
2129e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
2139e7b2b25Sstefano_zampini       if (istrans[ij]) {
2149e7b2b25Sstefano_zampini         Mat T,lT;
2159e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2169e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
2179e7b2b25Sstefano_zampini         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) (transposed) is not of type MATIS",i,j);
2189e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
2199e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
2209e7b2b25Sstefano_zampini       } else {
2215e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
2225e3038f0Sstefano_zampini         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) is not of type MATIS",i,j);
2239e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
2249e7b2b25Sstefano_zampini       }
2255e3038f0Sstefano_zampini 
2265e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
2275e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
2289e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
2295e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
2305e3038f0Sstefano_zampini       if (lr[i] && l1 != lr[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lr[i],l1);
2315e3038f0Sstefano_zampini       if (lc[j] && l2 != lc[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lc[j],l2);
2325e3038f0Sstefano_zampini       lr[i] = l1;
2335e3038f0Sstefano_zampini       lc[j] = l2;
2345e3038f0Sstefano_zampini 
2355e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
2365e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
2375e3038f0Sstefano_zampini     }
2385e3038f0Sstefano_zampini   }
2395e3038f0Sstefano_zampini 
2405e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
2415e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
2425e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2435e3038f0Sstefano_zampini     rl2g = NULL;
2445e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2455e3038f0Sstefano_zampini       PetscInt n1,n2;
2465e3038f0Sstefano_zampini 
2475e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2489e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
2499e7b2b25Sstefano_zampini         Mat T;
2509e7b2b25Sstefano_zampini 
2519e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2529e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
2539e7b2b25Sstefano_zampini       } else {
2545e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
2559e7b2b25Sstefano_zampini       }
2565e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2575e3038f0Sstefano_zampini       if (!n1) continue;
2585e3038f0Sstefano_zampini       if (!rl2g) {
2595e3038f0Sstefano_zampini         rl2g = cl2g;
2605e3038f0Sstefano_zampini       } else {
2615e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2625e3038f0Sstefano_zampini         PetscBool      same;
2635e3038f0Sstefano_zampini 
2645e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2655e3038f0Sstefano_zampini         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap size %D != %D",i,j,n1,n2);
2665e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2675e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2685e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2695e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2705e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2715e3038f0Sstefano_zampini         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap",i,j);
2725e3038f0Sstefano_zampini       }
2735e3038f0Sstefano_zampini     }
2745e3038f0Sstefano_zampini   }
2755e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
2765e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
2775e3038f0Sstefano_zampini     rl2g = NULL;
2785e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
2795e3038f0Sstefano_zampini       PetscInt n1,n2;
2805e3038f0Sstefano_zampini 
2815e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
2829e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
2839e7b2b25Sstefano_zampini         Mat T;
2849e7b2b25Sstefano_zampini 
2859e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
2869e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
2879e7b2b25Sstefano_zampini       } else {
2885e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
2899e7b2b25Sstefano_zampini       }
2905e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2915e3038f0Sstefano_zampini       if (!n1) continue;
2925e3038f0Sstefano_zampini       if (!rl2g) {
2935e3038f0Sstefano_zampini         rl2g = cl2g;
2945e3038f0Sstefano_zampini       } else {
2955e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2965e3038f0Sstefano_zampini         PetscBool      same;
2975e3038f0Sstefano_zampini 
2985e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2995e3038f0Sstefano_zampini         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap size %D != %D",j,i,n1,n2);
3005e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
3015e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
3025e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
3035e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
3045e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
3055e3038f0Sstefano_zampini         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap",j,i);
3065e3038f0Sstefano_zampini       }
3075e3038f0Sstefano_zampini     }
3085e3038f0Sstefano_zampini   }
3095e3038f0Sstefano_zampini #endif
3105e3038f0Sstefano_zampini 
3115e3038f0Sstefano_zampini   B = NULL;
3125e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
3135b003df0Sstefano_zampini     PetscInt stl;
3145b003df0Sstefano_zampini 
3155e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
3165e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
3175e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3185b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
3195e3038f0Sstefano_zampini       Mat            usedmat;
3205e3038f0Sstefano_zampini       Mat_IS         *matis;
3215e3038f0Sstefano_zampini       const PetscInt *idxs;
3225e3038f0Sstefano_zampini 
3235e3038f0Sstefano_zampini       /* local IS for local NEST */
3245b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
3255e3038f0Sstefano_zampini 
3265e3038f0Sstefano_zampini       /* l2gmap */
3275e3038f0Sstefano_zampini       j = 0;
3285e3038f0Sstefano_zampini       usedmat = nest[i][j];
3299e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
3309e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
3319e7b2b25Sstefano_zampini 
3329e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3339e7b2b25Sstefano_zampini         Mat T;
3349e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3359e7b2b25Sstefano_zampini         usedmat = T;
3369e7b2b25Sstefano_zampini       }
33782d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3385e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3395e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
3409e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3419e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3429e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3439e7b2b25Sstefano_zampini       } else {
3445e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3455e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3469e7b2b25Sstefano_zampini       }
3475e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
3485e3038f0Sstefano_zampini       stl += lr[i];
3495e3038f0Sstefano_zampini     }
3505e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
3515e3038f0Sstefano_zampini 
3525e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
3535e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
3545e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3555b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
3565e3038f0Sstefano_zampini       Mat            usedmat;
3575e3038f0Sstefano_zampini       Mat_IS         *matis;
3585e3038f0Sstefano_zampini       const PetscInt *idxs;
3595e3038f0Sstefano_zampini 
3605e3038f0Sstefano_zampini       /* local IS for local NEST */
3615b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
3625e3038f0Sstefano_zampini 
3635e3038f0Sstefano_zampini       /* l2gmap */
3645e3038f0Sstefano_zampini       j = 0;
3655e3038f0Sstefano_zampini       usedmat = nest[j][i];
3669e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
3679e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
3689e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3699e7b2b25Sstefano_zampini         Mat T;
3709e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3719e7b2b25Sstefano_zampini         usedmat = T;
3729e7b2b25Sstefano_zampini       }
37382d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3745e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3755e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
3769e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3779e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3789e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3799e7b2b25Sstefano_zampini       } else {
3805e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3815e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3829e7b2b25Sstefano_zampini       }
3835e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
3845e3038f0Sstefano_zampini       stl += lc[i];
3855e3038f0Sstefano_zampini     }
3865e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
3875e3038f0Sstefano_zampini 
3885e3038f0Sstefano_zampini     /* Create MATIS */
3895e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
3905e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
3915e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
3925e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
3935e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
3945e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
3955e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3965e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3975e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
3989e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
3999e7b2b25Sstefano_zampini       if (istrans[i]) {
4009e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
4019e7b2b25Sstefano_zampini       }
4029e7b2b25Sstefano_zampini     }
4035e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
4045e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
4055e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4065e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4075e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
4085e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
4095e3038f0Sstefano_zampini     } else {
4105e3038f0Sstefano_zampini       *newmat = B;
4115e3038f0Sstefano_zampini     }
4125e3038f0Sstefano_zampini   } else {
4135e3038f0Sstefano_zampini     if (lreuse) {
4145e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4155e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
4165e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
4175e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
4185e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
4199e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
4209e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
4219e7b2b25Sstefano_zampini             }
4225e3038f0Sstefano_zampini           }
4235e3038f0Sstefano_zampini         }
4245e3038f0Sstefano_zampini       }
4255e3038f0Sstefano_zampini     } else {
4265b003df0Sstefano_zampini       PetscInt stl;
4275b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
4285b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
4295b003df0Sstefano_zampini         stl  += lr[i];
4305e3038f0Sstefano_zampini       }
4315b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
4325b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
4335b003df0Sstefano_zampini         stl  += lc[i];
4345e3038f0Sstefano_zampini       }
4355e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
4369e7b2b25Sstefano_zampini       if (istrans[i]) {
4379e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
4389e7b2b25Sstefano_zampini       }
4395e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
4405e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
4415e3038f0Sstefano_zampini     }
4425e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4435e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4445e3038f0Sstefano_zampini   }
4455e3038f0Sstefano_zampini 
4465b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
4475b003df0Sstefano_zampini   convert = PETSC_FALSE;
4485b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
4495b003df0Sstefano_zampini   if (convert) {
4505b003df0Sstefano_zampini     Mat              M;
4515b003df0Sstefano_zampini     MatISLocalFields lf;
4525b003df0Sstefano_zampini     PetscContainer   c;
4535b003df0Sstefano_zampini 
4545b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4555b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
4565b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
4575b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
4585b003df0Sstefano_zampini 
4595b003df0Sstefano_zampini     /* attach local fields to the matrix */
4605b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
4615b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
4625b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
4635b003df0Sstefano_zampini       PetscInt n,st;
4645b003df0Sstefano_zampini 
4655b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
4665b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
4675b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
4685b003df0Sstefano_zampini     }
4695b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
4705b003df0Sstefano_zampini       PetscInt n,st;
4715b003df0Sstefano_zampini 
4725b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
4735b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
4745b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
4755b003df0Sstefano_zampini     }
4765b003df0Sstefano_zampini     lf->nr = nr;
4775b003df0Sstefano_zampini     lf->nc = nc;
4785b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
4795b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
4805b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
4815b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
4825b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
4835b003df0Sstefano_zampini   }
4845b003df0Sstefano_zampini 
4855e3038f0Sstefano_zampini   /* Free workspace */
4865e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4875e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
4885e3038f0Sstefano_zampini   }
4895e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
4905e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
4915e3038f0Sstefano_zampini   }
4929e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
4935b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
4945e3038f0Sstefano_zampini   PetscFunctionReturn(0);
4955e3038f0Sstefano_zampini }
4965e3038f0Sstefano_zampini 
497ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
498ad219c80Sstefano_zampini {
499ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
500ad219c80Sstefano_zampini   Vec               ll,rr;
501ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
502ad219c80Sstefano_zampini   PetscScalar       *x,*y;
503ad219c80Sstefano_zampini   PetscErrorCode    ierr;
504ad219c80Sstefano_zampini 
505ad219c80Sstefano_zampini   PetscFunctionBegin;
506ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
507ad219c80Sstefano_zampini   if (l) {
508ad219c80Sstefano_zampini     ll   = matis->y;
509ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
510ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
511ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
512ad219c80Sstefano_zampini   } else {
513ad219c80Sstefano_zampini     ll = NULL;
514ad219c80Sstefano_zampini   }
515ad219c80Sstefano_zampini   if (r) {
516ad219c80Sstefano_zampini     rr   = matis->x;
517ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
518ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
519ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
520ad219c80Sstefano_zampini   } else {
521ad219c80Sstefano_zampini     rr = NULL;
522ad219c80Sstefano_zampini   }
523ad219c80Sstefano_zampini   if (ll) {
524ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
525ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
526ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
527ad219c80Sstefano_zampini   }
528ad219c80Sstefano_zampini   if (rr) {
529ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
530ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
531ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
532ad219c80Sstefano_zampini   }
533ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
534ad219c80Sstefano_zampini   PetscFunctionReturn(0);
535ad219c80Sstefano_zampini }
536ad219c80Sstefano_zampini 
5377fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
5387fa8f2d3SStefano Zampini {
5397fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
5407fa8f2d3SStefano Zampini   MatInfo        info;
5417fa8f2d3SStefano Zampini   PetscReal      isend[6],irecv[6];
5427fa8f2d3SStefano Zampini   PetscInt       bs;
5437fa8f2d3SStefano Zampini   PetscErrorCode ierr;
5447fa8f2d3SStefano Zampini 
5457fa8f2d3SStefano Zampini   PetscFunctionBegin;
5467fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
5477fa8f2d3SStefano Zampini   if (matis->A->ops->getinfo) {
5487fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
5497fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
5507fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
5517fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
5527fa8f2d3SStefano Zampini     isend[3] = info.memory;
5537fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
5547fa8f2d3SStefano Zampini   } else {
5557fa8f2d3SStefano Zampini     isend[0] = 0.;
5567fa8f2d3SStefano Zampini     isend[1] = 0.;
5577fa8f2d3SStefano Zampini     isend[2] = 0.;
5587fa8f2d3SStefano Zampini     isend[3] = 0.;
5597fa8f2d3SStefano Zampini     isend[4] = 0.;
5607fa8f2d3SStefano Zampini   }
5617fa8f2d3SStefano Zampini   isend[5] = matis->A->num_ass;
5627fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
5637fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
5647fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
5657fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
5667fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
5677fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
5687fa8f2d3SStefano Zampini     ginfo->assemblies   = isend[5];
5697fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
5707fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
5717fa8f2d3SStefano Zampini 
5727fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
5737fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
5747fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
5757fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
5767fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
5777fa8f2d3SStefano Zampini     ginfo->assemblies   = irecv[5];
5787fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
5797fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
5807fa8f2d3SStefano Zampini 
5817fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
5827fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
5837fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
5847fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
5857fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
5867fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
587d7f69cd0SStefano Zampini   }
588d7f69cd0SStefano Zampini   ginfo->block_size        = bs;
589d7f69cd0SStefano Zampini   ginfo->fill_ratio_given  = 0;
590d7f69cd0SStefano Zampini   ginfo->fill_ratio_needed = 0;
591d7f69cd0SStefano Zampini   ginfo->factor_mallocs    = 0;
5925e3038f0Sstefano_zampini   PetscFunctionReturn(0);
5935e3038f0Sstefano_zampini }
5945e3038f0Sstefano_zampini 
595d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
596d7f69cd0SStefano Zampini {
597d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
598d7f69cd0SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
599d7f69cd0SStefano Zampini   PetscBool              notset = PETSC_FALSE,cong = PETSC_TRUE;
600d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
601d7f69cd0SStefano Zampini 
602d7f69cd0SStefano Zampini   PetscFunctionBegin;
603d7f69cd0SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
604d7f69cd0SStefano Zampini     PetscBool rcong,ccong;
605d7f69cd0SStefano Zampini 
606d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr);
607d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr);
608fa520230SStefano Zampini     cong = (PetscBool)(rcong || ccong);
609d7f69cd0SStefano Zampini   }
610d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) {
611d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
612d7f69cd0SStefano Zampini   } else {
613d7f69cd0SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,&notset);CHKERRQ(ierr);
614d7f69cd0SStefano Zampini     C = *B;
615d7f69cd0SStefano Zampini   }
616d7f69cd0SStefano Zampini 
617d7f69cd0SStefano Zampini   if (!notset) {
618d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
619d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
620d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
621d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
622d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
623d7f69cd0SStefano Zampini   }
624d7f69cd0SStefano Zampini 
625d7f69cd0SStefano Zampini   /* perform local transposition */
626d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
627d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
628d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
629d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
630d7f69cd0SStefano Zampini 
631d7f69cd0SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
632d7f69cd0SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
633d7f69cd0SStefano Zampini 
634d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
635d7f69cd0SStefano Zampini     if (!cong) {
636d7f69cd0SStefano Zampini       ierr = MatDestroy(B);CHKERRQ(ierr);
637d7f69cd0SStefano Zampini     }
638d7f69cd0SStefano Zampini     *B = C;
639d7f69cd0SStefano Zampini   } else {
640d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
641d7f69cd0SStefano Zampini   }
642d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
643d7f69cd0SStefano Zampini }
644d7f69cd0SStefano Zampini 
6453fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
6463fd1c9e7SStefano Zampini {
6473fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
6483fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6493fd1c9e7SStefano Zampini 
6503fd1c9e7SStefano Zampini   PetscFunctionBegin;
6513fd1c9e7SStefano Zampini   if (!D) { /* this code branch is used by MatShift_IS */
6523fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
6533fd1c9e7SStefano Zampini   } else {
6543fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6553fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6563fd1c9e7SStefano Zampini   }
6573fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
6583fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
6593fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6603fd1c9e7SStefano Zampini }
6613fd1c9e7SStefano Zampini 
6623fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
6633fd1c9e7SStefano Zampini {
6643fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6653fd1c9e7SStefano Zampini 
6663fd1c9e7SStefano Zampini   PetscFunctionBegin;
6673fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
6683fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6693fd1c9e7SStefano Zampini }
6703fd1c9e7SStefano Zampini 
671f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
672f26d0771SStefano Zampini {
673f26d0771SStefano Zampini   PetscErrorCode ierr;
674f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
675f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
676f26d0771SStefano Zampini 
677f26d0771SStefano Zampini   PetscFunctionBegin;
678f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
679f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
680f26d0771SStefano Zampini #endif
681f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
682f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
683f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
684f26d0771SStefano Zampini   PetscFunctionReturn(0);
685f26d0771SStefano Zampini }
686f26d0771SStefano Zampini 
687f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
688f26d0771SStefano Zampini {
689f26d0771SStefano Zampini   PetscErrorCode ierr;
690f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
691f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
692f26d0771SStefano Zampini 
693f26d0771SStefano Zampini   PetscFunctionBegin;
694f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
695f26d0771SStefano 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);
696f26d0771SStefano Zampini #endif
697f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
698f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
699f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
700f26d0771SStefano Zampini   PetscFunctionReturn(0);
701f26d0771SStefano Zampini }
702f26d0771SStefano Zampini 
703f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
704a8116848SStefano Zampini {
705a8116848SStefano Zampini   PetscInt      *owners = map->range;
706a8116848SStefano Zampini   PetscInt       n      = map->n;
707a8116848SStefano Zampini   PetscSF        sf;
708a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
709a8116848SStefano Zampini   PetscSFNode   *ridxs;
710a8116848SStefano Zampini   PetscMPIInt    rank;
711a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
712a8116848SStefano Zampini   PetscErrorCode ierr;
713a8116848SStefano Zampini 
714a8116848SStefano Zampini   PetscFunctionBegin;
715fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
716a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
717a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
718a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
719a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
720a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
721a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
722a8116848SStefano Zampini     const PetscInt idx = idxs[r];
723a8116848SStefano 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);
724a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
725a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
726a8116848SStefano Zampini     }
727a8116848SStefano Zampini     ridxs[r].rank = p;
728a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
729a8116848SStefano Zampini   }
730a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
731a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
732a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
733a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
734f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
735a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
736f0ae7da4SStefano Zampini 
737f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
738a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
739a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
740a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
741a8116848SStefano Zampini     start -= cum;
742a8116848SStefano Zampini     cum = 0;
743a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
744a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
745a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
746a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
747a8116848SStefano Zampini   }
748a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
749a8116848SStefano Zampini   /* Compress and put in indices */
750a8116848SStefano Zampini   for (r = 0; r < n; ++r)
751a8116848SStefano Zampini     if (lidxs[r] >= 0) {
752a8116848SStefano Zampini       if (work) work[len] = work[r];
753a8116848SStefano Zampini       lidxs[len++] = r;
754a8116848SStefano Zampini     }
755a8116848SStefano Zampini   if (on) *on = len;
756a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
757a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
758a8116848SStefano Zampini   PetscFunctionReturn(0);
759a8116848SStefano Zampini }
760a8116848SStefano Zampini 
761a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
762a8116848SStefano Zampini {
763a8116848SStefano Zampini   Mat               locmat,newlocmat;
764a8116848SStefano Zampini   Mat_IS            *newmatis;
765a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
766a8116848SStefano Zampini   Vec               rtest,ltest;
767a8116848SStefano Zampini   const PetscScalar *array;
768a8116848SStefano Zampini #endif
769a8116848SStefano Zampini   const PetscInt    *idxs;
770a8116848SStefano Zampini   PetscInt          i,m,n;
771a8116848SStefano Zampini   PetscErrorCode    ierr;
772a8116848SStefano Zampini 
773a8116848SStefano Zampini   PetscFunctionBegin;
774a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
775a8116848SStefano Zampini     PetscBool ismatis;
776a8116848SStefano Zampini 
777a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
778a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
779a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
780a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
781a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
782a8116848SStefano Zampini   }
783a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
784a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
785a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
786a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
787a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
788a8116848SStefano Zampini   for (i=0;i<n;i++) {
789a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
790a8116848SStefano Zampini   }
791a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
792a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
793a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
794a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
795a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
796fd479f66SMatthew 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]));
797a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
798a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
799a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
800a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
801a8116848SStefano Zampini   for (i=0;i<n;i++) {
802a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
803a8116848SStefano Zampini   }
804a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
805a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
806a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
807a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
808a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
809fd479f66SMatthew 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]));
810a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
811a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
812a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
813a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
814a8116848SStefano Zampini #endif
815a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
816a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
817a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
818a8116848SStefano Zampini     IS                     is;
819a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
8206dd40735SStefano Zampini     PetscInt               ll,newloc;
821a8116848SStefano Zampini     MPI_Comm               comm;
822a8116848SStefano Zampini 
823a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
824a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
825a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
826a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
827a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
828a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
829a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
830a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
831f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
832a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
8333d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
8343d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
835a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
836a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
837a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
838a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
839a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
8403d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
841a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
842a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8433d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
844a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
845a8116848SStefano Zampini         lidxs[newloc] = i;
846a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
847a8116848SStefano Zampini       }
848a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
849a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
850a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
851a8116848SStefano Zampini     /* local is to extract local submatrix */
852a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
853a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
854a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
855a8116848SStefano Zampini       PetscBool cong;
856a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
857a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
858a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
859a8116848SStefano Zampini     }
860a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
861a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
862a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
863a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
864a8116848SStefano Zampini     } else {
865a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
866a8116848SStefano Zampini 
867a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
868a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
869f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
870a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
8713d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
872a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
873a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
874a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
875a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
876a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
8773d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
878a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
879a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8803d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
881a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
882a8116848SStefano Zampini           lidxs[newloc] = i;
883a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
884a8116848SStefano Zampini         }
885a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
886a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
887a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
888a8116848SStefano Zampini       /* local is to extract local submatrix */
889a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
890a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
891a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
892a8116848SStefano Zampini     }
893a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
894a8116848SStefano Zampini   } else {
895a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
896a8116848SStefano Zampini   }
897a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
898a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
899a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
900a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
901a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
902a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
903a8116848SStefano Zampini   }
904a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
905a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
906a8116848SStefano Zampini   PetscFunctionReturn(0);
907a8116848SStefano Zampini }
908a8116848SStefano Zampini 
909a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
9102b404112SStefano Zampini {
9112b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
9122b404112SStefano Zampini   PetscBool      ismatis;
9132b404112SStefano Zampini   PetscErrorCode ierr;
9142b404112SStefano Zampini 
9152b404112SStefano Zampini   PetscFunctionBegin;
9162b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
9172b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
9182b404112SStefano Zampini   b = (Mat_IS*)B->data;
9192b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
9202b404112SStefano Zampini   PetscFunctionReturn(0);
9212b404112SStefano Zampini }
9222b404112SStefano Zampini 
923a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
9246bd84002SStefano Zampini {
925527b2640SStefano Zampini   Vec               v;
926527b2640SStefano Zampini   const PetscScalar *array;
927527b2640SStefano Zampini   PetscInt          i,n;
9286bd84002SStefano Zampini   PetscErrorCode    ierr;
9296bd84002SStefano Zampini 
9306bd84002SStefano Zampini   PetscFunctionBegin;
931527b2640SStefano Zampini   *missing = PETSC_FALSE;
932527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
933527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
934527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
935527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
936527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
937527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
938527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
939527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
940527b2640SStefano Zampini   if (d) {
941527b2640SStefano Zampini     *d = -1;
942527b2640SStefano Zampini     if (*missing) {
943527b2640SStefano Zampini       PetscInt rstart;
944527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
945527b2640SStefano Zampini       *d = i+rstart;
946527b2640SStefano Zampini     }
947527b2640SStefano Zampini   }
9486bd84002SStefano Zampini   PetscFunctionReturn(0);
9496bd84002SStefano Zampini }
9506bd84002SStefano Zampini 
951cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
95228f4e0baSStefano Zampini {
95328f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
95428f4e0baSStefano Zampini   const PetscInt *gidxs;
9554f2d7cafSStefano Zampini   PetscInt       nleaves;
95628f4e0baSStefano Zampini   PetscErrorCode ierr;
95728f4e0baSStefano Zampini 
95828f4e0baSStefano Zampini   PetscFunctionBegin;
9594f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
96028f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
9613bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9624f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
9634f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
9643bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9654f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
966a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
9673d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
968a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
969a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9703d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
971a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9723d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
973a8116848SStefano Zampini   } else {
974a8116848SStefano Zampini     matis->csf = matis->sf;
975a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
976a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
977a8116848SStefano Zampini   }
97828f4e0baSStefano Zampini   PetscFunctionReturn(0);
97928f4e0baSStefano Zampini }
9802e1947a5SStefano Zampini 
981eb82efa4SStefano Zampini /*@
982a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
983a88811baSStefano Zampini 
984a88811baSStefano Zampini    Collective on MPI_Comm
985a88811baSStefano Zampini 
986a88811baSStefano Zampini    Input Parameters:
987a88811baSStefano Zampini +  B - the matrix
988a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
989a88811baSStefano Zampini            (same value is used for all local rows)
990a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
991a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
992a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
993a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
994a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
995a88811baSStefano Zampini            the diagonal entry even if it is zero.
996a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
997a88811baSStefano Zampini            submatrix (same value is used for all local rows).
998a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
999a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1000a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1001a88811baSStefano Zampini            structure. The size of this array is equal to the number
1002a88811baSStefano Zampini            of local rows, i.e 'm'.
1003a88811baSStefano Zampini 
1004a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1005a88811baSStefano Zampini 
1006a88811baSStefano Zampini    Level: intermediate
1007a88811baSStefano Zampini 
1008a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1009a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1010a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1011a88811baSStefano Zampini 
1012a88811baSStefano Zampini .keywords: matrix
1013a88811baSStefano Zampini 
10143c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1015a88811baSStefano Zampini @*/
10162e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10172e1947a5SStefano Zampini {
10182e1947a5SStefano Zampini   PetscErrorCode ierr;
10192e1947a5SStefano Zampini 
10202e1947a5SStefano Zampini   PetscFunctionBegin;
10212e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
10222e1947a5SStefano Zampini   PetscValidType(B,1);
10232e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
10242e1947a5SStefano Zampini   PetscFunctionReturn(0);
10252e1947a5SStefano Zampini }
10262e1947a5SStefano Zampini 
10277230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10282e1947a5SStefano Zampini {
10292e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
103028f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
10312e1947a5SStefano Zampini   PetscErrorCode ierr;
10322e1947a5SStefano Zampini 
10332e1947a5SStefano Zampini   PetscFunctionBegin;
10346c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1035cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
10364f2d7cafSStefano Zampini 
10374f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
10384f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
10394f2d7cafSStefano Zampini 
10404f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
10414f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
10424f2d7cafSStefano Zampini 
104328f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
104428f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
104528f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
104628f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
10474f2d7cafSStefano Zampini 
10484f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
104928f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
10504f2d7cafSStefano Zampini 
10514f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
105228f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10534f2d7cafSStefano Zampini 
10544f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
105528f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10562e1947a5SStefano Zampini   PetscFunctionReturn(0);
10572e1947a5SStefano Zampini }
1058b4319ba4SBarry Smith 
10593927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
10603927de2eSStefano Zampini {
10613927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
10623927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1063ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
10643927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
10653927de2eSStefano Zampini   PetscInt        lrows,lcols;
10663927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
10673927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
10683927de2eSStefano Zampini   PetscBool       isdense,issbaij;
10693927de2eSStefano Zampini   PetscErrorCode  ierr;
10703927de2eSStefano Zampini 
10713927de2eSStefano Zampini   PetscFunctionBegin;
10723927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
10733927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
10743927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
10753927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
10763927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
10773927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1078ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1079ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
10807230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1081ecf5a873SStefano Zampini   } else {
1082ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1083ecf5a873SStefano Zampini   }
1084ecf5a873SStefano Zampini 
10853927de2eSStefano Zampini   if (issbaij) {
10863927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
10873927de2eSStefano Zampini   }
10883927de2eSStefano Zampini   /*
1089ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
10903927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
10913927de2eSStefano Zampini   */
1092cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
10933927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
10943927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
10953927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
10963927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
10973927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
10983927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
10993927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
11003927de2eSStefano Zampini       row_ownership[j] = i;
11013927de2eSStefano Zampini     }
11023927de2eSStefano Zampini   }
11037230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
11043927de2eSStefano Zampini 
11053927de2eSStefano Zampini   /*
11063927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
11073927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
11083927de2eSStefano Zampini   */
11093927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
11103927de2eSStefano Zampini   /* preallocation as a MATAIJ */
11113927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
11123927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
1113ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
11143927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
11153927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1116ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
11173927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11183927de2eSStefano Zampini           my_dnz[i] += 1;
11193927de2eSStefano Zampini         } else { /* offdiag block */
11203927de2eSStefano Zampini           my_onz[i] += 1;
11213927de2eSStefano Zampini         }
11223927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
11233927de2eSStefano Zampini         if (i != j) {
11243927de2eSStefano Zampini           owner = row_ownership[index_col];
11253927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
11263927de2eSStefano Zampini             my_dnz[j] += 1;
11273927de2eSStefano Zampini           } else {
11283927de2eSStefano Zampini             my_onz[j] += 1;
11293927de2eSStefano Zampini           }
11303927de2eSStefano Zampini         }
11313927de2eSStefano Zampini       }
11323927de2eSStefano Zampini     }
1133bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1134bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1135bb1015c3SStefano Zampini     PetscBool      done;
1136bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1137*938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1138bb1015c3SStefano Zampini     jptr = jj;
1139bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1140bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1141bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1142bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1143bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1144bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1145bb1015c3SStefano Zampini           my_dnz[i] += 1;
1146bb1015c3SStefano Zampini         } else { /* offdiag block */
1147bb1015c3SStefano Zampini           my_onz[i] += 1;
1148bb1015c3SStefano Zampini         }
1149bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1150bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1151bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1152bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1153bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1154bb1015c3SStefano Zampini           } else {
1155bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1156bb1015c3SStefano Zampini           }
1157bb1015c3SStefano Zampini         }
1158bb1015c3SStefano Zampini       }
1159bb1015c3SStefano Zampini     }
1160bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1161*938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1162bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
11633927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
11643927de2eSStefano Zampini       const PetscInt *cols;
1165ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
11663927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11673927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
11683927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1169ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
11703927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11713927de2eSStefano Zampini           my_dnz[i] += 1;
11723927de2eSStefano Zampini         } else { /* offdiag block */
11733927de2eSStefano Zampini           my_onz[i] += 1;
11743927de2eSStefano Zampini         }
11753927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1176d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
11773927de2eSStefano Zampini           owner = row_ownership[index_col];
11783927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1179d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
11803927de2eSStefano Zampini           } else {
1181d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
11823927de2eSStefano Zampini           }
11833927de2eSStefano Zampini         }
11843927de2eSStefano Zampini       }
11853927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11863927de2eSStefano Zampini     }
11873927de2eSStefano Zampini   }
1188ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1189ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
11907230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1191ecf5a873SStefano Zampini   }
11923927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1193ecf5a873SStefano Zampini 
1194ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
11953927de2eSStefano Zampini   if (maxreduce) {
11963927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11973927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1198bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11993927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
12003927de2eSStefano Zampini   } else {
12013927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
12023927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1203bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
12043927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
12053927de2eSStefano Zampini   }
12063927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
12073927de2eSStefano Zampini 
12083927de2eSStefano Zampini   /* Resize preallocation if overestimated */
12093927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
12103927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
12113927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
12123927de2eSStefano Zampini   }
12131670daf9Sstefano_zampini 
12141670daf9Sstefano_zampini   /* Set preallocation */
12153927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
12163927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
12173927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
12183927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
12193927de2eSStefano Zampini   }
12203927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12213927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12223927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
12233927de2eSStefano Zampini   if (issbaij) {
12243927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
12253927de2eSStefano Zampini   }
12263927de2eSStefano Zampini   PetscFunctionReturn(0);
12273927de2eSStefano Zampini }
12283927de2eSStefano Zampini 
12297230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1230b7ce53b6SStefano Zampini {
1231b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1232d9a9e74cSStefano Zampini   Mat            local_mat;
1233b7ce53b6SStefano Zampini   /* info on mat */
12343cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1235b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1236b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1237b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1238b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1239b9ed4604SStefano Zampini #endif
12407c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1241b7ce53b6SStefano Zampini   /* values insertion */
1242b7ce53b6SStefano Zampini   PetscScalar    *array;
1243b7ce53b6SStefano Zampini   /* work */
1244b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1245b7ce53b6SStefano Zampini 
1246b7ce53b6SStefano Zampini   PetscFunctionBegin;
1247b7ce53b6SStefano Zampini   /* get info from mat */
12487c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
12497c03b4e8SStefano Zampini   if (nsubdomains == 1) {
12501670daf9Sstefano_zampini     Mat            B;
12511670daf9Sstefano_zampini     IS             rows,cols;
1252acdf38a7Sstefano_zampini     IS             irows,icols;
12531670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
12541670daf9Sstefano_zampini 
12551670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
12561670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
12571670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
12581670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
12591670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
12601670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1261acdf38a7Sstefano_zampini     ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1262acdf38a7Sstefano_zampini     ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1263acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr);
1264acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr);
1265acdf38a7Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
1266acdf38a7Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
1267acdf38a7Sstefano_zampini     ierr = MatConvert(matis->A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
1268acdf38a7Sstefano_zampini     ierr = MatGetSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1269acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1270acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1271acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
12727c03b4e8SStefano Zampini     PetscFunctionReturn(0);
12737c03b4e8SStefano Zampini   }
1274b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1275b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
12763cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1277b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1278b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
1279686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1280b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1281b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1282b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1283b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1284b9ed4604SStefano Zampini   lb[0] = isseqdense;
1285b9ed4604SStefano Zampini   lb[1] = isseqaij;
1286b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1287b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1288b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1289b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1290b9ed4604SStefano Zampini #endif
1291b7ce53b6SStefano Zampini 
1292b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
12933927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
12943cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
12953927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
1296b9ed4604SStefano Zampini     if (!isseqsbaij) {
1297b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1298b9ed4604SStefano Zampini     } else {
1299b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1300b9ed4604SStefano Zampini     }
13013927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1302b7ce53b6SStefano Zampini   } else {
13033cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1304b7ce53b6SStefano Zampini     /* some checks */
1305b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1306b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
13073cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
13086c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
13096c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
13106c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
13116c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
13126c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1313b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1314b7ce53b6SStefano Zampini   }
1315d9a9e74cSStefano Zampini 
1316b9ed4604SStefano Zampini   if (isseqsbaij) {
1317d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1318d9a9e74cSStefano Zampini   } else {
1319d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1320d9a9e74cSStefano Zampini     local_mat = matis->A;
1321d9a9e74cSStefano Zampini   }
1322686e3a49SStefano Zampini 
1323b7ce53b6SStefano Zampini   /* Set values */
1324ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1325b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
1326ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
1327ecf5a873SStefano Zampini 
1328ecf5a873SStefano Zampini     if (local_rows != local_cols) {
1329ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
1330ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1331ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
1332ecf5a873SStefano Zampini     } else {
1333ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
1334ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1335ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
1336ecf5a873SStefano Zampini     }
1337b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1338d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
1339ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
1340d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
1341ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
1342ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
1343ecf5a873SStefano Zampini     } else {
1344ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
1345ecf5a873SStefano Zampini     }
1346686e3a49SStefano Zampini   } else if (isseqaij) {
1347ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1348686e3a49SStefano Zampini     PetscBool done;
1349686e3a49SStefano Zampini 
1350d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1351*938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1352d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1353686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1354ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1355686e3a49SStefano Zampini     }
1356d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1357*938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1358d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1359686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1360ecf5a873SStefano Zampini     PetscInt i;
1361c0962df8SStefano Zampini 
1362686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1363686e3a49SStefano Zampini       PetscInt       j;
1364ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1365686e3a49SStefano Zampini 
1366ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1367ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1368ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1369686e3a49SStefano Zampini     }
1370b7ce53b6SStefano Zampini   }
1371b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1372d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1373b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1374b9ed4604SStefano Zampini   if (isseqdense) {
1375b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1376b7ce53b6SStefano Zampini   }
1377b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1378b7ce53b6SStefano Zampini }
1379b7ce53b6SStefano Zampini 
1380b7ce53b6SStefano Zampini /*@
1381b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1382b7ce53b6SStefano Zampini 
1383b7ce53b6SStefano Zampini   Input Parameter:
1384b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1385b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1386b7ce53b6SStefano Zampini 
1387b7ce53b6SStefano Zampini   Output Parameter:
1388b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1389b7ce53b6SStefano Zampini 
1390b7ce53b6SStefano Zampini   Level: developer
1391b7ce53b6SStefano Zampini 
1392eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1393b7ce53b6SStefano Zampini 
1394b7ce53b6SStefano Zampini .seealso: MATIS
1395b7ce53b6SStefano Zampini @*/
1396b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1397b7ce53b6SStefano Zampini {
1398b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1399b7ce53b6SStefano Zampini 
1400b7ce53b6SStefano Zampini   PetscFunctionBegin;
1401b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1402b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1403b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1404b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1405b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1406b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
14076c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1408b7ce53b6SStefano Zampini   }
1409b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1410b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1411b7ce53b6SStefano Zampini }
1412b7ce53b6SStefano Zampini 
1413ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1414ad6194a2SStefano Zampini {
1415ad6194a2SStefano Zampini   PetscErrorCode ierr;
1416ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1417ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1418ad6194a2SStefano Zampini   Mat            B,localmat;
1419ad6194a2SStefano Zampini 
1420ad6194a2SStefano Zampini   PetscFunctionBegin;
1421ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1422ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1423ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1424e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1425ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1426ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1427b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1428ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1429ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1430ad6194a2SStefano Zampini   *newmat = B;
1431ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1432ad6194a2SStefano Zampini }
1433ad6194a2SStefano Zampini 
1434a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
143569796d55SStefano Zampini {
143669796d55SStefano Zampini   PetscErrorCode ierr;
143769796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
143869796d55SStefano Zampini   PetscBool      local_sym;
143969796d55SStefano Zampini 
144069796d55SStefano Zampini   PetscFunctionBegin;
144169796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1442b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
144369796d55SStefano Zampini   PetscFunctionReturn(0);
144469796d55SStefano Zampini }
144569796d55SStefano Zampini 
1446a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
144769796d55SStefano Zampini {
144869796d55SStefano Zampini   PetscErrorCode ierr;
144969796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
145069796d55SStefano Zampini   PetscBool      local_sym;
145169796d55SStefano Zampini 
145269796d55SStefano Zampini   PetscFunctionBegin;
145369796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1454b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
145569796d55SStefano Zampini   PetscFunctionReturn(0);
145669796d55SStefano Zampini }
145769796d55SStefano Zampini 
145845471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
145945471136SStefano Zampini {
146045471136SStefano Zampini   PetscErrorCode ierr;
146145471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
146245471136SStefano Zampini   PetscBool      local_sym;
146345471136SStefano Zampini 
146445471136SStefano Zampini   PetscFunctionBegin;
146545471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
146645471136SStefano Zampini     *flg = PETSC_FALSE;
146745471136SStefano Zampini     PetscFunctionReturn(0);
146845471136SStefano Zampini   }
146945471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
147045471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
147145471136SStefano Zampini   PetscFunctionReturn(0);
147245471136SStefano Zampini }
147345471136SStefano Zampini 
1474a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1475b4319ba4SBarry Smith {
1476dfbe8321SBarry Smith   PetscErrorCode ierr;
1477b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1478b4319ba4SBarry Smith 
1479b4319ba4SBarry Smith   PetscFunctionBegin;
14806bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1481e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1482e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
14836bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
14846bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
14853fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1486a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1487a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1488a8116848SStefano Zampini   if (b->sf != b->csf) {
1489a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1490a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1491a8116848SStefano Zampini   }
149228f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
149328f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1494bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1495dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1496bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1497b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1498b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
14992e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1500cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1501b4319ba4SBarry Smith   PetscFunctionReturn(0);
1502b4319ba4SBarry Smith }
1503b4319ba4SBarry Smith 
1504a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1505b4319ba4SBarry Smith {
1506dfbe8321SBarry Smith   PetscErrorCode ierr;
1507b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1508b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1509b4319ba4SBarry Smith 
1510b4319ba4SBarry Smith   PetscFunctionBegin;
1511b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1512e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1513e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1514b4319ba4SBarry Smith 
1515b4319ba4SBarry Smith   /* multiply the local matrix */
1516b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1517b4319ba4SBarry Smith 
1518b4319ba4SBarry Smith   /* scatter product back into global memory */
15192dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1520e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1521e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1522b4319ba4SBarry Smith   PetscFunctionReturn(0);
1523b4319ba4SBarry Smith }
1524b4319ba4SBarry Smith 
1525a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15262e74eeadSLisandro Dalcin {
1527650997f4SStefano Zampini   Vec            temp_vec;
15282e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15292e74eeadSLisandro Dalcin 
15302e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1531650997f4SStefano Zampini   if (v3 != v2) {
1532650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1533650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1534650997f4SStefano Zampini   } else {
1535650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1536650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1537650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1538650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1539650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1540650997f4SStefano Zampini   }
15412e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15422e74eeadSLisandro Dalcin }
15432e74eeadSLisandro Dalcin 
1544a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
15452e74eeadSLisandro Dalcin {
15462e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
15472e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15482e74eeadSLisandro Dalcin 
1549e176bc59SStefano Zampini   PetscFunctionBegin;
15502e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1551e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1552e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15532e74eeadSLisandro Dalcin 
15542e74eeadSLisandro Dalcin   /* multiply the local matrix */
1555e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
15562e74eeadSLisandro Dalcin 
15572e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1558e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1559e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1560e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15612e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15622e74eeadSLisandro Dalcin }
15632e74eeadSLisandro Dalcin 
1564a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15652e74eeadSLisandro Dalcin {
1566650997f4SStefano Zampini   Vec            temp_vec;
15672e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15682e74eeadSLisandro Dalcin 
15692e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1570650997f4SStefano Zampini   if (v3 != v2) {
1571650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1572650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1573650997f4SStefano Zampini   } else {
1574650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1575650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1576650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1577650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1578650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1579650997f4SStefano Zampini   }
15802e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15812e74eeadSLisandro Dalcin }
15822e74eeadSLisandro Dalcin 
1583a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1584b4319ba4SBarry Smith {
1585b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1586dfbe8321SBarry Smith   PetscErrorCode ierr;
1587b4319ba4SBarry Smith   PetscViewer    sviewer;
1588ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1589b4319ba4SBarry Smith 
1590b4319ba4SBarry Smith   PetscFunctionBegin;
1591ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1592ee2491ecSStefano Zampini   if (isascii)  {
1593ee2491ecSStefano Zampini     PetscViewerFormat format;
1594ee2491ecSStefano Zampini 
1595ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1596ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1597ee2491ecSStefano Zampini   }
1598ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
15993f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1600b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
16013f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
16026e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1603b4319ba4SBarry Smith   PetscFunctionReturn(0);
1604b4319ba4SBarry Smith }
1605b4319ba4SBarry Smith 
1606a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1607b4319ba4SBarry Smith {
1608dfbe8321SBarry Smith   PetscErrorCode ierr;
1609e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1610b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1611b4319ba4SBarry Smith   IS             from,to;
1612e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1613b4319ba4SBarry Smith 
1614b4319ba4SBarry Smith   PetscFunctionBegin;
1615784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1616e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
16173bbff08aSStefano Zampini   /* Destroy any previous data */
161870cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
161970cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
16203fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1621e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1622e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
16231c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
162428f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
162528f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
16263bbff08aSStefano Zampini 
16273bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1628fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1629fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1630fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1631fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1632b4319ba4SBarry Smith 
1633b4319ba4SBarry Smith   /* Create the local matrix A */
1634e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1635e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1636e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1637e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1638f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1639e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1640e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1641e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1642ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1643ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1644b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1645b4319ba4SBarry Smith 
1646f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1647b4319ba4SBarry Smith     /* Create the local work vectors */
16483bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1649b4319ba4SBarry Smith 
1650e176bc59SStefano Zampini     /* setup the global to local scatters */
1651e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1652e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1653784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1654e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1655e176bc59SStefano Zampini     if (rmapping != cmapping) {
1656e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1657e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1658e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1659e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1660e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1661e176bc59SStefano Zampini     } else {
1662e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1663e176bc59SStefano Zampini       is->cctx = is->rctx;
1664e176bc59SStefano Zampini     }
16653fd1c9e7SStefano Zampini 
16663fd1c9e7SStefano Zampini     /* interface counter vector (local) */
16673fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
16683fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
16693fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16703fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16713fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16723fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16733fd1c9e7SStefano Zampini 
16743fd1c9e7SStefano Zampini     /* free workspace */
1675e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1676e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
16776bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
16786bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1679f26d0771SStefano Zampini   }
168048ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1681b4319ba4SBarry Smith   PetscFunctionReturn(0);
1682b4319ba4SBarry Smith }
1683b4319ba4SBarry Smith 
1684a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
16852e74eeadSLisandro Dalcin {
16862e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
16872e74eeadSLisandro Dalcin   PetscErrorCode ierr;
168897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
168997563a80SStefano Zampini   PetscInt       i,zm,zn;
169097563a80SStefano Zampini #endif
1691f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
16922e74eeadSLisandro Dalcin 
16932e74eeadSLisandro Dalcin   PetscFunctionBegin;
16942e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1695f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
169697563a80SStefano Zampini   /* count negative indices */
169797563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
169897563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
16992e74eeadSLisandro Dalcin #endif
170097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
170197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
170297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
170397563a80SStefano Zampini   /* count negative indices (should be the same as before) */
170497563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
170597563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
170697563a80SStefano 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");
170797563a80SStefano 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");
170897563a80SStefano Zampini #endif
17092e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
17102e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
17112e74eeadSLisandro Dalcin }
17122e74eeadSLisandro Dalcin 
1713a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
171497563a80SStefano Zampini {
171597563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
171697563a80SStefano Zampini   PetscErrorCode ierr;
171797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
171897563a80SStefano Zampini   PetscInt       i,zm,zn;
171997563a80SStefano Zampini #endif
1720f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
172197563a80SStefano Zampini 
172297563a80SStefano Zampini   PetscFunctionBegin;
172397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1724f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
172597563a80SStefano Zampini   /* count negative indices */
172697563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
172797563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
172897563a80SStefano Zampini #endif
172997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
173097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
173197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
173297563a80SStefano Zampini   /* count negative indices (should be the same as before) */
173397563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
173497563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
173597563a80SStefano 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");
173697563a80SStefano 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");
173797563a80SStefano Zampini #endif
173897563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
173997563a80SStefano Zampini   PetscFunctionReturn(0);
174097563a80SStefano Zampini }
174197563a80SStefano Zampini 
1742a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1743b4319ba4SBarry Smith {
1744dfbe8321SBarry Smith   PetscErrorCode ierr;
1745b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1746b4319ba4SBarry Smith 
1747b4319ba4SBarry Smith   PetscFunctionBegin;
1748b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1749b4319ba4SBarry Smith   PetscFunctionReturn(0);
1750b4319ba4SBarry Smith }
1751b4319ba4SBarry Smith 
1752a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1753f0006bf2SLisandro Dalcin {
1754f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1755f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1756f0006bf2SLisandro Dalcin 
1757f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1758f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1759f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1760f0006bf2SLisandro Dalcin }
1761f0006bf2SLisandro Dalcin 
1762f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1763f0ae7da4SStefano Zampini {
1764f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1765f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1766f0ae7da4SStefano Zampini 
1767f0ae7da4SStefano Zampini   PetscFunctionBegin;
1768f0ae7da4SStefano Zampini   if (!n) {
1769f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1770f0ae7da4SStefano Zampini   } else {
1771f0ae7da4SStefano Zampini     PetscInt i;
1772f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1773f0ae7da4SStefano Zampini 
1774f0ae7da4SStefano Zampini     if (columns) {
1775f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1776f0ae7da4SStefano Zampini     } else {
1777f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1778f0ae7da4SStefano Zampini     }
1779f0ae7da4SStefano Zampini     if (diag != 0.) {
1780f0ae7da4SStefano Zampini       const PetscScalar *array;
1781f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1782f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1783f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1784f0ae7da4SStefano Zampini       }
1785f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1786f0ae7da4SStefano Zampini     }
1787f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1788f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1789f0ae7da4SStefano Zampini   }
1790f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1791f0ae7da4SStefano Zampini }
1792f0ae7da4SStefano Zampini 
1793f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
17942e74eeadSLisandro Dalcin {
17956e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
17966e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
17976e520ac8SStefano Zampini   PetscInt       *lrows;
17982e74eeadSLisandro Dalcin   PetscErrorCode ierr;
17992e74eeadSLisandro Dalcin 
18002e74eeadSLisandro Dalcin   PetscFunctionBegin;
1801f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1802f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1803f0ae7da4SStefano Zampini     PetscBool cong;
1804f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1805f0ae7da4SStefano 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");
1806f0ae7da4SStefano 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");
1807f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1808f0ae7da4SStefano Zampini   }
1809f0ae7da4SStefano Zampini #endif
18106e520ac8SStefano Zampini   /* get locally owned rows */
1811f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
18126e520ac8SStefano Zampini   /* fix right hand side if needed */
18136e520ac8SStefano Zampini   if (x && b) {
18146e520ac8SStefano Zampini     const PetscScalar *xx;
18156e520ac8SStefano Zampini     PetscScalar       *bb;
18166e520ac8SStefano Zampini 
18176e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
18186e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
18196e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
18206e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
18216e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
18222e74eeadSLisandro Dalcin   }
18236e520ac8SStefano Zampini   /* get rows associated to the local matrices */
18243d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
18256e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
18266e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
18276e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
18286e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
18296e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18306e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18316e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18326e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
18336e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1834f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
18356e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18362e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18372e74eeadSLisandro Dalcin }
18382e74eeadSLisandro Dalcin 
1839f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1840b4319ba4SBarry Smith {
1841dfbe8321SBarry Smith   PetscErrorCode ierr;
1842b4319ba4SBarry Smith 
1843b4319ba4SBarry Smith   PetscFunctionBegin;
1844f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1845f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1846f0ae7da4SStefano Zampini }
18472205254eSKarl Rupp 
1848f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1849f0ae7da4SStefano Zampini {
1850f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1851f0ae7da4SStefano Zampini 
1852f0ae7da4SStefano Zampini   PetscFunctionBegin;
1853f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1854b4319ba4SBarry Smith   PetscFunctionReturn(0);
1855b4319ba4SBarry Smith }
1856b4319ba4SBarry Smith 
1857a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1858b4319ba4SBarry Smith {
1859b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1860dfbe8321SBarry Smith   PetscErrorCode ierr;
1861b4319ba4SBarry Smith 
1862b4319ba4SBarry Smith   PetscFunctionBegin;
1863b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1864b4319ba4SBarry Smith   PetscFunctionReturn(0);
1865b4319ba4SBarry Smith }
1866b4319ba4SBarry Smith 
1867a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1868b4319ba4SBarry Smith {
1869b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1870dfbe8321SBarry Smith   PetscErrorCode ierr;
1871b4319ba4SBarry Smith 
1872b4319ba4SBarry Smith   PetscFunctionBegin;
1873b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1874b4319ba4SBarry Smith   PetscFunctionReturn(0);
1875b4319ba4SBarry Smith }
1876b4319ba4SBarry Smith 
1877a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1878b4319ba4SBarry Smith {
1879b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1880b4319ba4SBarry Smith 
1881b4319ba4SBarry Smith   PetscFunctionBegin;
1882b4319ba4SBarry Smith   *local = is->A;
1883b4319ba4SBarry Smith   PetscFunctionReturn(0);
1884b4319ba4SBarry Smith }
1885b4319ba4SBarry Smith 
1886b4319ba4SBarry Smith /*@
1887b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1888b4319ba4SBarry Smith 
1889b4319ba4SBarry Smith   Input Parameter:
1890b4319ba4SBarry Smith .  mat - the matrix
1891b4319ba4SBarry Smith 
1892b4319ba4SBarry Smith   Output Parameter:
1893eb82efa4SStefano Zampini .  local - the local matrix
1894b4319ba4SBarry Smith 
1895b4319ba4SBarry Smith   Level: advanced
1896b4319ba4SBarry Smith 
1897b4319ba4SBarry Smith   Notes:
1898b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1899b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1900b4319ba4SBarry Smith   of the MatSetValues() operation.
1901b4319ba4SBarry Smith 
1902b4319ba4SBarry Smith .seealso: MATIS
1903b4319ba4SBarry Smith @*/
19047087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1905b4319ba4SBarry Smith {
19064ac538c5SBarry Smith   PetscErrorCode ierr;
1907b4319ba4SBarry Smith 
1908b4319ba4SBarry Smith   PetscFunctionBegin;
19090700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1910b4319ba4SBarry Smith   PetscValidPointer(local,2);
19114ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1912b4319ba4SBarry Smith   PetscFunctionReturn(0);
1913b4319ba4SBarry Smith }
1914b4319ba4SBarry Smith 
1915a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
19163b03a366Sstefano_zampini {
19173b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
19183b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
19193b03a366Sstefano_zampini   PetscErrorCode ierr;
19203b03a366Sstefano_zampini 
19213b03a366Sstefano_zampini   PetscFunctionBegin;
19224e4c7dbeSStefano Zampini   if (is->A) {
19233b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
19243b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1925f0ae7da4SStefano 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);
19264e4c7dbeSStefano Zampini   }
19273b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
19283b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
19293b03a366Sstefano_zampini   is->A = local;
19303b03a366Sstefano_zampini   PetscFunctionReturn(0);
19313b03a366Sstefano_zampini }
19323b03a366Sstefano_zampini 
19333b03a366Sstefano_zampini /*@
1934eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
19353b03a366Sstefano_zampini 
19363b03a366Sstefano_zampini   Input Parameter:
19373b03a366Sstefano_zampini .  mat - the matrix
1938eb82efa4SStefano Zampini .  local - the local matrix
19393b03a366Sstefano_zampini 
19403b03a366Sstefano_zampini   Output Parameter:
19413b03a366Sstefano_zampini 
19423b03a366Sstefano_zampini   Level: advanced
19433b03a366Sstefano_zampini 
19443b03a366Sstefano_zampini   Notes:
19453b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
19463b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
19473b03a366Sstefano_zampini 
19483b03a366Sstefano_zampini .seealso: MATIS
19493b03a366Sstefano_zampini @*/
19503b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
19513b03a366Sstefano_zampini {
19523b03a366Sstefano_zampini   PetscErrorCode ierr;
19533b03a366Sstefano_zampini 
19543b03a366Sstefano_zampini   PetscFunctionBegin;
19553b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1956b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
19573b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
19583b03a366Sstefano_zampini   PetscFunctionReturn(0);
19593b03a366Sstefano_zampini }
19603b03a366Sstefano_zampini 
1961a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
19626726f965SBarry Smith {
19636726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
19646726f965SBarry Smith   PetscErrorCode ierr;
19656726f965SBarry Smith 
19666726f965SBarry Smith   PetscFunctionBegin;
19676726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
19686726f965SBarry Smith   PetscFunctionReturn(0);
19696726f965SBarry Smith }
19706726f965SBarry Smith 
1971a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
19722e74eeadSLisandro Dalcin {
19732e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
19742e74eeadSLisandro Dalcin   PetscErrorCode ierr;
19752e74eeadSLisandro Dalcin 
19762e74eeadSLisandro Dalcin   PetscFunctionBegin;
19772e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
19782e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
19792e74eeadSLisandro Dalcin }
19802e74eeadSLisandro Dalcin 
1981a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
19822e74eeadSLisandro Dalcin {
19832e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
19842e74eeadSLisandro Dalcin   PetscErrorCode ierr;
19852e74eeadSLisandro Dalcin 
19862e74eeadSLisandro Dalcin   PetscFunctionBegin;
19872e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
1988e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
19892e74eeadSLisandro Dalcin 
19902e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
19912e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
1992e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1993e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19942e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
19952e74eeadSLisandro Dalcin }
19962e74eeadSLisandro Dalcin 
1997a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
19986726f965SBarry Smith {
19996726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
20006726f965SBarry Smith   PetscErrorCode ierr;
20016726f965SBarry Smith 
20026726f965SBarry Smith   PetscFunctionBegin;
20034e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
20046726f965SBarry Smith   PetscFunctionReturn(0);
20056726f965SBarry Smith }
20066726f965SBarry Smith 
2007f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
2008f26d0771SStefano Zampini {
2009f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
2010f26d0771SStefano Zampini   Mat_IS         *x;
2011f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2012f26d0771SStefano Zampini   PetscBool      ismatis;
2013f26d0771SStefano Zampini #endif
2014f26d0771SStefano Zampini   PetscErrorCode ierr;
2015f26d0771SStefano Zampini 
2016f26d0771SStefano Zampini   PetscFunctionBegin;
2017f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2018f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
2019f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
2020f26d0771SStefano Zampini #endif
2021f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
2022f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
2023f26d0771SStefano Zampini   PetscFunctionReturn(0);
2024f26d0771SStefano Zampini }
2025f26d0771SStefano Zampini 
2026f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
2027f26d0771SStefano Zampini {
2028f26d0771SStefano Zampini   Mat                    lA;
2029f26d0771SStefano Zampini   Mat_IS                 *matis;
2030f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2031f26d0771SStefano Zampini   IS                     is;
2032f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
2033f26d0771SStefano Zampini   PetscInt               nrg;
2034f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
2035f26d0771SStefano Zampini   PetscErrorCode         ierr;
2036f26d0771SStefano Zampini 
2037f26d0771SStefano Zampini   PetscFunctionBegin;
2038f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2039f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
2040f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
2041f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
2042f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2043f0ae7da4SStefano 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);
2044f26d0771SStefano Zampini #endif
2045f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
2046f26d0771SStefano Zampini   /* map from [0,nrl) to row */
2047f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
2048f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2049f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
2050f26d0771SStefano Zampini #else
2051f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
2052f26d0771SStefano Zampini #endif
2053f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
2054f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2055f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2056f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2057f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
2058f26d0771SStefano Zampini   /* compute new l2g map for columns */
2059f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2060f26d0771SStefano Zampini     const PetscInt *cg,*cl;
2061f26d0771SStefano Zampini     PetscInt       ncg;
2062f26d0771SStefano Zampini     PetscInt       ncl;
2063f26d0771SStefano Zampini 
2064f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2065f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2066f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2067f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2068f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2069f0ae7da4SStefano 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);
2070f26d0771SStefano Zampini #endif
2071f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2072f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2073f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2074f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2075f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2076f26d0771SStefano Zampini #else
2077f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2078f26d0771SStefano Zampini #endif
2079f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2080f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2081f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2082f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2083f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2084f26d0771SStefano Zampini   } else {
2085f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2086f26d0771SStefano Zampini     cl2g = rl2g;
2087f26d0771SStefano Zampini   }
2088f26d0771SStefano Zampini   /* create the MATIS submatrix */
2089f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2090f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2091f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2092f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2093b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2094f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2095f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2096f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2097f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2098f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2099f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2100f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2101f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2102f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2103f26d0771SStefano Zampini   /* remove unsupported ops */
2104f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2105f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2106f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2107f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2108f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2109f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2110f26d0771SStefano Zampini   PetscFunctionReturn(0);
2111f26d0771SStefano Zampini }
2112f26d0771SStefano Zampini 
2113284134d9SBarry Smith /*@
21143c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2115284134d9SBarry Smith        process but not across processes.
2116284134d9SBarry Smith 
2117284134d9SBarry Smith    Input Parameters:
2118284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2119e176bc59SStefano Zampini .     bs      - block size of the matrix
2120df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2121e176bc59SStefano Zampini .     rmap    - local to global map for rows
2122e176bc59SStefano Zampini -     cmap    - local to global map for cols
2123284134d9SBarry Smith 
2124284134d9SBarry Smith    Output Parameter:
2125284134d9SBarry Smith .    A - the resulting matrix
2126284134d9SBarry Smith 
21278e6c10adSSatish Balay    Level: advanced
21288e6c10adSSatish Balay 
21293c212e90SHong Zhang    Notes: See MATIS for more details.
21306fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
21316fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
21323c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2133284134d9SBarry Smith 
2134284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2135284134d9SBarry Smith @*/
2136e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2137284134d9SBarry Smith {
2138284134d9SBarry Smith   PetscErrorCode ierr;
2139284134d9SBarry Smith 
2140284134d9SBarry Smith   PetscFunctionBegin;
21416fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2142284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
21436fdf41d1SStefano Zampini   if (bs > 0) {
2144d3ee2243SStefano Zampini     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
21456fdf41d1SStefano Zampini   }
2146284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
2147284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2148e176bc59SStefano Zampini   if (rmap && cmap) {
2149e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2150e176bc59SStefano Zampini   } else if (!rmap) {
2151e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2152e176bc59SStefano Zampini   } else {
2153e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2154e176bc59SStefano Zampini   }
2155284134d9SBarry Smith   PetscFunctionReturn(0);
2156284134d9SBarry Smith }
2157284134d9SBarry Smith 
2158b4319ba4SBarry Smith /*MC
2159f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2160b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2161b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2162b4319ba4SBarry Smith    product is handled "implicitly".
2163b4319ba4SBarry Smith 
2164b4319ba4SBarry Smith    Operations Provided:
21656726f965SBarry Smith +  MatMult()
21662e74eeadSLisandro Dalcin .  MatMultAdd()
21672e74eeadSLisandro Dalcin .  MatMultTranspose()
21682e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
21696726f965SBarry Smith .  MatZeroEntries()
21706726f965SBarry Smith .  MatSetOption()
21712e74eeadSLisandro Dalcin .  MatZeroRows()
21722e74eeadSLisandro Dalcin .  MatSetValues()
217397563a80SStefano Zampini .  MatSetValuesBlocked()
21746726f965SBarry Smith .  MatSetValuesLocal()
217597563a80SStefano Zampini .  MatSetValuesBlockedLocal()
21762e74eeadSLisandro Dalcin .  MatScale()
21772e74eeadSLisandro Dalcin .  MatGetDiagonal()
21782b404112SStefano Zampini .  MatMissingDiagonal()
21792b404112SStefano Zampini .  MatDuplicate()
21802b404112SStefano Zampini .  MatCopy()
2181f26d0771SStefano Zampini .  MatAXPY()
2182f26d0771SStefano Zampini .  MatGetSubMatrix()
2183f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2184d7f69cd0SStefano Zampini .  MatTranspose()
21856726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2186b4319ba4SBarry Smith 
2187b4319ba4SBarry Smith    Options Database Keys:
2188b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2189b4319ba4SBarry Smith 
2190b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
2191b4319ba4SBarry Smith 
2192b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2193b4319ba4SBarry Smith 
2194b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2195eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2196b4319ba4SBarry Smith 
2197b4319ba4SBarry Smith   Level: advanced
2198b4319ba4SBarry Smith 
2199f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2200b4319ba4SBarry Smith 
2201b4319ba4SBarry Smith M*/
2202b4319ba4SBarry Smith 
22038cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2204b4319ba4SBarry Smith {
2205dfbe8321SBarry Smith   PetscErrorCode ierr;
2206b4319ba4SBarry Smith   Mat_IS         *b;
2207b4319ba4SBarry Smith 
2208b4319ba4SBarry Smith   PetscFunctionBegin;
2209b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2210b4319ba4SBarry Smith   A->data = (void*)b;
2211b4319ba4SBarry Smith 
2212e176bc59SStefano Zampini   /* matrix ops */
2213e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2214b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
22152e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
22162e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
22172e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2218b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2219b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
22202e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
222198921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2222b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2223f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
22242e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2225f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2226b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2227b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2228b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
22296726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
22302e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
22312e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
22326726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
223369796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
223469796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
223545471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2236ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
22376bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
22382b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2239659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
2240a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
2241f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
22423fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
22433fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2244d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
22457fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
2246ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
2247b4319ba4SBarry Smith 
2248b7ce53b6SStefano Zampini   /* special MATIS functions */
2249bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
2250bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2251b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
22522e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2253cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
225417667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2255b4319ba4SBarry Smith   PetscFunctionReturn(0);
2256b4319ba4SBarry Smith }
2257