xref: /petsc/src/mat/impls/is/matis.c (revision 82d731617afdfda75c2bcf34408f251793f5ed77)
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 
16cf0a3239SStefano Zampini #undef __FUNCT__
176989cf23SStefano Zampini #define __FUNCT__ "MatISContainerDestroy_Private"
186989cf23SStefano Zampini static PetscErrorCode MatISContainerDestroy_Private(void *ptr)
196989cf23SStefano Zampini {
206989cf23SStefano Zampini   PetscErrorCode ierr;
216989cf23SStefano Zampini 
226989cf23SStefano Zampini   PetscFunctionBeginUser;
236989cf23SStefano Zampini   ierr = PetscFree(ptr); CHKERRQ(ierr);
246989cf23SStefano Zampini   PetscFunctionReturn(0);
256989cf23SStefano Zampini }
266989cf23SStefano Zampini 
276989cf23SStefano Zampini #undef __FUNCT__
286989cf23SStefano Zampini #define __FUNCT__ "MatConvert_MPIAIJ_IS"
296989cf23SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
306989cf23SStefano Zampini {
316989cf23SStefano Zampini   Mat_MPIAIJ             *aij  = (Mat_MPIAIJ*)A->data;
326989cf23SStefano Zampini   Mat_SeqAIJ             *diag = (Mat_SeqAIJ*)(aij->A->data);
336989cf23SStefano Zampini   Mat_SeqAIJ             *offd = (Mat_SeqAIJ*)(aij->B->data);
346989cf23SStefano Zampini   Mat                    lA;
356989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
366989cf23SStefano Zampini   IS                     is;
376989cf23SStefano Zampini   MPI_Comm               comm;
386989cf23SStefano Zampini   void                   *ptrs[2];
396989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
406989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
416989cf23SStefano Zampini   PetscInt               *di,*dj,*oi,*oj;
426989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
43e363d98aSStefano Zampini   PetscInt               lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
446989cf23SStefano Zampini   PetscErrorCode         ierr;
456989cf23SStefano Zampini 
466989cf23SStefano Zampini   PetscFunctionBeginUser;
476989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
486989cf23SStefano Zampini   if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present");
496989cf23SStefano Zampini 
506989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
516989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
526989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
536989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
546989cf23SStefano Zampini   di   = diag->i;
556989cf23SStefano Zampini   dj   = diag->j;
566989cf23SStefano Zampini   dd   = diag->a;
576989cf23SStefano Zampini   oc   = aij->B->cmap->n;
586989cf23SStefano Zampini   oi   = offd->i;
596989cf23SStefano Zampini   oj   = offd->j;
606989cf23SStefano Zampini   od   = offd->a;
616989cf23SStefano Zampini   nnz  = diag->i[dr] + offd->i[dr];
626989cf23SStefano Zampini 
636989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
646989cf23SStefano Zampini   ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
656989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
666989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
67e363d98aSStefano Zampini   if (dr) {
686989cf23SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
696989cf23SStefano Zampini     for (i=0; i<dc; i++) aux[i]    = i+stc;
706989cf23SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i];
716989cf23SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
72e363d98aSStefano Zampini     lc   = dc+oc;
73e363d98aSStefano Zampini   } else {
74e363d98aSStefano Zampini     ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
75e363d98aSStefano Zampini     lc   = 0;
76e363d98aSStefano Zampini   }
776989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
786989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
796989cf23SStefano Zampini 
806989cf23SStefano Zampini   /* create MATIS object */
816989cf23SStefano Zampini   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
826989cf23SStefano Zampini   ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
836989cf23SStefano Zampini   ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
846989cf23SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
856989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
866989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
876989cf23SStefano Zampini 
886989cf23SStefano Zampini   /* merge local matrices */
896989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
906989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
916989cf23SStefano Zampini   ii   = aux;
926989cf23SStefano Zampini   jj   = aux+dr+1;
936989cf23SStefano Zampini   aa   = data;
946989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
956989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
966989cf23SStefano Zampini   {
976989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
986989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
996989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
1006989cf23SStefano Zampini   }
1016989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
1026989cf23SStefano Zampini   ii   = aux;
1036989cf23SStefano Zampini   jj   = aux+dr+1;
1046989cf23SStefano Zampini   aa   = data;
105e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
1066989cf23SStefano Zampini 
1076989cf23SStefano Zampini   /* create containers to destroy the data */
1086989cf23SStefano Zampini   ptrs[0] = aux;
1096989cf23SStefano Zampini   ptrs[1] = data;
1106989cf23SStefano Zampini   for (i=0; i<2; i++) {
1116989cf23SStefano Zampini     PetscContainer c;
1126989cf23SStefano Zampini 
1136989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
1146989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
1156989cf23SStefano Zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroy_Private);CHKERRQ(ierr);
1166989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
1176989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
1186989cf23SStefano Zampini   }
1196989cf23SStefano Zampini 
1206989cf23SStefano Zampini   /* finalize matrix */
1216989cf23SStefano Zampini   ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
1226989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
1236989cf23SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1246989cf23SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1256989cf23SStefano Zampini   PetscFunctionReturn(0);
1266989cf23SStefano Zampini }
1276989cf23SStefano Zampini 
1286989cf23SStefano Zampini #undef __FUNCT__
129cf0a3239SStefano Zampini #define __FUNCT__ "MatISSetUpSF"
130cf0a3239SStefano Zampini /*@
1313d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
132cf0a3239SStefano Zampini 
133cf0a3239SStefano Zampini    Collective on MPI_Comm
134cf0a3239SStefano Zampini 
135cf0a3239SStefano Zampini    Input Parameters:
136cf0a3239SStefano Zampini +  A - the matrix
137cf0a3239SStefano Zampini 
138cf0a3239SStefano Zampini    Level: advanced
139cf0a3239SStefano Zampini 
1403d996552SStefano Zampini    Notes: This function does not need to be called by the user.
141cf0a3239SStefano Zampini 
142cf0a3239SStefano Zampini .keywords: matrix
143cf0a3239SStefano Zampini 
144cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
145cf0a3239SStefano Zampini @*/
146cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
147cf0a3239SStefano Zampini {
148cf0a3239SStefano Zampini   PetscErrorCode ierr;
149cf0a3239SStefano Zampini 
150cf0a3239SStefano Zampini   PetscFunctionBegin;
151cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
152cf0a3239SStefano Zampini   PetscValidType(A,1);
153cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
154cf0a3239SStefano Zampini   PetscFunctionReturn(0);
155cf0a3239SStefano Zampini }
156a72627d2SStefano Zampini 
15728f4e0baSStefano Zampini #undef __FUNCT__
1585e3038f0Sstefano_zampini #define __FUNCT__ "MatConvert_Nest_IS"
1595e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1605e3038f0Sstefano_zampini {
1615e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
1625e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
1635e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
1645e3038f0Sstefano_zampini   MPI_Comm               comm;
1655e3038f0Sstefano_zampini   PetscInt               *lr,*lc,*lrb,*lcb,*l2gidxs;
1665e3038f0Sstefano_zampini   PetscInt               sti,stl,i,j,nr,nc,rbs,cbs;
1675e3038f0Sstefano_zampini   PetscBool              convert,lreuse;
1685e3038f0Sstefano_zampini   PetscErrorCode         ierr;
1695e3038f0Sstefano_zampini 
1705e3038f0Sstefano_zampini   PetscFunctionBeginUser;
1715e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
1725e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
1735e3038f0Sstefano_zampini   rnest  = NULL;
1745e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
1755e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
1765e3038f0Sstefano_zampini 
1775e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1785e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
1795e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
1805e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
1815e3038f0Sstefano_zampini     if (isnest) {
1825e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
1835e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
1845e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
1855e3038f0Sstefano_zampini     }
1865e3038f0Sstefano_zampini   }
1875e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1885e3038f0Sstefano_zampini   ierr = PetscCalloc4(nr,&lr,nc,&lc,nr,&lrb,nc,&lcb);CHKERRQ(ierr);
1895e3038f0Sstefano_zampini   ierr = PetscCalloc5(nr,&isrow,nc,&iscol,
1905e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
1915e3038f0Sstefano_zampini                       nr*nc,&snest);CHKERRQ(ierr);
1925e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
1935e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
1945e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
1955e3038f0Sstefano_zampini       PetscBool ismatis;
1965e3038f0Sstefano_zampini       PetscInt  l1,l2,ij=i*nc+j;
1975e3038f0Sstefano_zampini 
1985e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
1995e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2005e3038f0Sstefano_zampini 
2015e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
2025e3038f0Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
2035e3038f0Sstefano_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);
2045e3038f0Sstefano_zampini 
2055e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
2065e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
2075e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
2085e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
2095e3038f0Sstefano_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);
2105e3038f0Sstefano_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);
2115e3038f0Sstefano_zampini       lr[i] = l1;
2125e3038f0Sstefano_zampini       lc[j] = l2;
2135e3038f0Sstefano_zampini       ierr  = MatGetBlockSizes(snest[ij],&l1,&l2);CHKERRQ(ierr);
2145e3038f0Sstefano_zampini       if (lrb[i] && l1 != lrb[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid block size %D != %D",i,j,lrb[i],l1);
2155e3038f0Sstefano_zampini       if (lcb[j] && l2 != lcb[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid block size %D != %D",i,j,lcb[j],l2);
2165e3038f0Sstefano_zampini       lrb[i] = l1;
2175e3038f0Sstefano_zampini       lcb[j] = l2;
2185e3038f0Sstefano_zampini 
2195e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
2205e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
2215e3038f0Sstefano_zampini     }
2225e3038f0Sstefano_zampini   }
2235e3038f0Sstefano_zampini 
2245e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
2255e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
2265e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2275e3038f0Sstefano_zampini     rl2g = NULL;
2285e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2295e3038f0Sstefano_zampini       PetscInt n1,n2;
2305e3038f0Sstefano_zampini 
2315e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2325e3038f0Sstefano_zampini       ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
2335e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2345e3038f0Sstefano_zampini       if (!n1) continue;
2355e3038f0Sstefano_zampini       if (!rl2g) {
2365e3038f0Sstefano_zampini         rl2g = cl2g;
2375e3038f0Sstefano_zampini       } else {
2385e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2395e3038f0Sstefano_zampini         PetscBool      same;
2405e3038f0Sstefano_zampini 
2415e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2425e3038f0Sstefano_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);
2435e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2445e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2455e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2465e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2475e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2485e3038f0Sstefano_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);
2495e3038f0Sstefano_zampini       }
2505e3038f0Sstefano_zampini     }
2515e3038f0Sstefano_zampini   }
2525e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
2535e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
2545e3038f0Sstefano_zampini     rl2g = NULL;
2555e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
2565e3038f0Sstefano_zampini       PetscInt n1,n2;
2575e3038f0Sstefano_zampini 
2585e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
2595e3038f0Sstefano_zampini       ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
2605e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2615e3038f0Sstefano_zampini       if (!n1) continue;
2625e3038f0Sstefano_zampini       if (!rl2g) {
2635e3038f0Sstefano_zampini         rl2g = cl2g;
2645e3038f0Sstefano_zampini       } else {
2655e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2665e3038f0Sstefano_zampini         PetscBool      same;
2675e3038f0Sstefano_zampini 
2685e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2695e3038f0Sstefano_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);
2705e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2715e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2725e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2735e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2745e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2755e3038f0Sstefano_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);
2765e3038f0Sstefano_zampini       }
2775e3038f0Sstefano_zampini     }
2785e3038f0Sstefano_zampini   }
2795e3038f0Sstefano_zampini #endif
2805e3038f0Sstefano_zampini 
2815e3038f0Sstefano_zampini   B = NULL;
2825e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
2835e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
2845e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
2855e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
2865e3038f0Sstefano_zampini     for (i=0,sti=0,stl=0;i<nr;i++) {
2875e3038f0Sstefano_zampini       Mat            usedmat;
2885e3038f0Sstefano_zampini       Mat_IS         *matis;
2895e3038f0Sstefano_zampini       const PetscInt *idxs;
2905e3038f0Sstefano_zampini       PetscInt       n = lr[i]/lrb[i];
2915e3038f0Sstefano_zampini 
2925e3038f0Sstefano_zampini       /* local IS for local NEST */
2935e3038f0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr);
2945e3038f0Sstefano_zampini       sti  += n;
2955e3038f0Sstefano_zampini 
2965e3038f0Sstefano_zampini       /* l2gmap */
2975e3038f0Sstefano_zampini       j = 0;
2985e3038f0Sstefano_zampini       usedmat = nest[i][j];
2995e3038f0Sstefano_zampini       while (!usedmat && j < nc) usedmat = nest[i][j++];
300*82d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3015e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3025e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
3035e3038f0Sstefano_zampini       ierr  = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3045e3038f0Sstefano_zampini       ierr  = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3055e3038f0Sstefano_zampini       ierr  = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
3065e3038f0Sstefano_zampini       stl += lr[i];
3075e3038f0Sstefano_zampini     }
3085e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
3095e3038f0Sstefano_zampini 
3105e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
3115e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
3125e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3135e3038f0Sstefano_zampini     for (i=0,sti=0,stl=0;i<nc;i++) {
3145e3038f0Sstefano_zampini       Mat            usedmat;
3155e3038f0Sstefano_zampini       Mat_IS         *matis;
3165e3038f0Sstefano_zampini       const PetscInt *idxs;
3175e3038f0Sstefano_zampini       PetscInt       n = lc[i]/lcb[i];
3185e3038f0Sstefano_zampini 
3195e3038f0Sstefano_zampini       /* local IS for local NEST */
3205e3038f0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr);
3215e3038f0Sstefano_zampini       sti  += n;
3225e3038f0Sstefano_zampini 
3235e3038f0Sstefano_zampini       /* l2gmap */
3245e3038f0Sstefano_zampini       j = 0;
3255e3038f0Sstefano_zampini       usedmat = nest[j][i];
3265e3038f0Sstefano_zampini       while (!usedmat && j < nr) usedmat = nest[j++][i];
327*82d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3285e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3295e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
3305e3038f0Sstefano_zampini       ierr  = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3315e3038f0Sstefano_zampini       ierr  = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3325e3038f0Sstefano_zampini       ierr  = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
3335e3038f0Sstefano_zampini       stl += lc[i];
3345e3038f0Sstefano_zampini     }
3355e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
3365e3038f0Sstefano_zampini 
3375e3038f0Sstefano_zampini     /* Create MATIS */
3385e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
3395e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
3405e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
3415e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
3425e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
3435e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
3445e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3455e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3465e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
3475e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
3485e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
3495e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3505e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3515e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
3525e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
3535e3038f0Sstefano_zampini     } else {
3545e3038f0Sstefano_zampini       *newmat = B;
3555e3038f0Sstefano_zampini     }
3565e3038f0Sstefano_zampini   } else {
3575e3038f0Sstefano_zampini     if (lreuse) {
3585e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
3595e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
3605e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
3615e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
3625e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
3635e3038f0Sstefano_zampini           }
3645e3038f0Sstefano_zampini         }
3655e3038f0Sstefano_zampini       }
3665e3038f0Sstefano_zampini     } else {
3675e3038f0Sstefano_zampini       for (i=0,sti=0;i<nr;i++) {
3685e3038f0Sstefano_zampini         PetscInt n = lr[i]/lrb[i];
3695e3038f0Sstefano_zampini 
3705e3038f0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lrb[i],&islrow[i]);CHKERRQ(ierr);
3715e3038f0Sstefano_zampini         sti  += n;
3725e3038f0Sstefano_zampini       }
3735e3038f0Sstefano_zampini       for (i=0,sti=0;i<nc;i++) {
3745e3038f0Sstefano_zampini         PetscInt n = lc[i]/lcb[i];
3755e3038f0Sstefano_zampini 
3765e3038f0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,n,sti,lcb[i],&islcol[i]);CHKERRQ(ierr);
3775e3038f0Sstefano_zampini         sti  += n;
3785e3038f0Sstefano_zampini       }
3795e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
3805e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
3815e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
3825e3038f0Sstefano_zampini     }
3835e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3845e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3855e3038f0Sstefano_zampini   }
3865e3038f0Sstefano_zampini 
3875e3038f0Sstefano_zampini   /* Free workspace */
3885e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
3895e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
3905e3038f0Sstefano_zampini   }
3915e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
3925e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
3935e3038f0Sstefano_zampini   }
3945e3038f0Sstefano_zampini   ierr = PetscFree4(lr,lc,lrb,lcb);CHKERRQ(ierr);
3955e3038f0Sstefano_zampini   ierr = PetscFree5(isrow,iscol,islrow,islcol,snest);CHKERRQ(ierr);
3965e3038f0Sstefano_zampini 
3975e3038f0Sstefano_zampini   /* Create local matrix in MATNEST format */
3985e3038f0Sstefano_zampini   convert = PETSC_FALSE;
3995e3038f0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
4005e3038f0Sstefano_zampini   if (convert) {
4015e3038f0Sstefano_zampini     Mat M;
4025e3038f0Sstefano_zampini 
4035e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4045e3038f0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
4055e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
4065e3038f0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
4075e3038f0Sstefano_zampini   }
4085e3038f0Sstefano_zampini 
4095e3038f0Sstefano_zampini   PetscFunctionReturn(0);
4105e3038f0Sstefano_zampini }
4115e3038f0Sstefano_zampini 
4125e3038f0Sstefano_zampini #undef __FUNCT__
413d7f69cd0SStefano Zampini #define __FUNCT__ "MatTranspose_IS"
414d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
415d7f69cd0SStefano Zampini {
416d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
417d7f69cd0SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
418d7f69cd0SStefano Zampini   PetscBool              notset = PETSC_FALSE,cong = PETSC_TRUE;
419d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
420d7f69cd0SStefano Zampini 
421d7f69cd0SStefano Zampini   PetscFunctionBegin;
422d7f69cd0SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
423d7f69cd0SStefano Zampini     PetscBool rcong,ccong;
424d7f69cd0SStefano Zampini 
425d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr);
426d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr);
427fa520230SStefano Zampini     cong = (PetscBool)(rcong || ccong);
428d7f69cd0SStefano Zampini   }
429d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) {
430d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
431d7f69cd0SStefano Zampini   } else {
432d7f69cd0SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,&notset);CHKERRQ(ierr);
433d7f69cd0SStefano Zampini     C = *B;
434d7f69cd0SStefano Zampini   }
435d7f69cd0SStefano Zampini 
436d7f69cd0SStefano Zampini   if (!notset) {
437d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
438d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
439d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
440d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
441d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
442d7f69cd0SStefano Zampini   }
443d7f69cd0SStefano Zampini 
444d7f69cd0SStefano Zampini   /* perform local transposition */
445d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
446d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
447d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
448d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
449d7f69cd0SStefano Zampini 
450d7f69cd0SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
451d7f69cd0SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
452d7f69cd0SStefano Zampini 
453d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
454d7f69cd0SStefano Zampini     if (!cong) {
455d7f69cd0SStefano Zampini       ierr = MatDestroy(B);CHKERRQ(ierr);
456d7f69cd0SStefano Zampini     }
457d7f69cd0SStefano Zampini     *B = C;
458d7f69cd0SStefano Zampini   } else {
459d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
460d7f69cd0SStefano Zampini   }
461d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
462d7f69cd0SStefano Zampini }
463d7f69cd0SStefano Zampini 
464d7f69cd0SStefano Zampini #undef __FUNCT__
4653fd1c9e7SStefano Zampini #define __FUNCT__ "MatDiagonalSet_IS"
4663fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
4673fd1c9e7SStefano Zampini {
4683fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
4693fd1c9e7SStefano Zampini   PetscErrorCode ierr;
4703fd1c9e7SStefano Zampini 
4713fd1c9e7SStefano Zampini   PetscFunctionBegin;
4723fd1c9e7SStefano Zampini   if (!D) { /* this code branch is used by MatShift_IS */
4733fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
4743fd1c9e7SStefano Zampini   } else {
4753fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4763fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4773fd1c9e7SStefano Zampini   }
4783fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
4793fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
4803fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
4813fd1c9e7SStefano Zampini }
4823fd1c9e7SStefano Zampini 
4833fd1c9e7SStefano Zampini #undef __FUNCT__
4843fd1c9e7SStefano Zampini #define __FUNCT__ "MatShift_IS"
4853fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
4863fd1c9e7SStefano Zampini {
4873fd1c9e7SStefano Zampini   PetscErrorCode ierr;
4883fd1c9e7SStefano Zampini 
4893fd1c9e7SStefano Zampini   PetscFunctionBegin;
4903fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
4913fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
4923fd1c9e7SStefano Zampini }
4933fd1c9e7SStefano Zampini 
4943fd1c9e7SStefano Zampini #undef __FUNCT__
495f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS"
496f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
497f26d0771SStefano Zampini {
498f26d0771SStefano Zampini   PetscErrorCode ierr;
499f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
500f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
501f26d0771SStefano Zampini 
502f26d0771SStefano Zampini   PetscFunctionBegin;
503f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
504f26d0771SStefano 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);
505f26d0771SStefano Zampini #endif
506f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
507f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
508f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
509f26d0771SStefano Zampini   PetscFunctionReturn(0);
510f26d0771SStefano Zampini }
511f26d0771SStefano Zampini 
512f26d0771SStefano Zampini #undef __FUNCT__
513f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS"
514f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
515f26d0771SStefano Zampini {
516f26d0771SStefano Zampini   PetscErrorCode ierr;
517f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
518f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
519f26d0771SStefano Zampini 
520f26d0771SStefano Zampini   PetscFunctionBegin;
521f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
522f26d0771SStefano 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);
523f26d0771SStefano Zampini #endif
524f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
525f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
526f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
527f26d0771SStefano Zampini   PetscFunctionReturn(0);
528f26d0771SStefano Zampini }
529f26d0771SStefano Zampini 
530f26d0771SStefano Zampini #undef __FUNCT__
531a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private"
532f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
533a8116848SStefano Zampini {
534a8116848SStefano Zampini   PetscInt      *owners = map->range;
535a8116848SStefano Zampini   PetscInt       n      = map->n;
536a8116848SStefano Zampini   PetscSF        sf;
537a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
538a8116848SStefano Zampini   PetscSFNode   *ridxs;
539a8116848SStefano Zampini   PetscMPIInt    rank;
540a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
541a8116848SStefano Zampini   PetscErrorCode ierr;
542a8116848SStefano Zampini 
543a8116848SStefano Zampini   PetscFunctionBegin;
544a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
545a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
546a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
547a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
548a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
549a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
550a8116848SStefano Zampini     const PetscInt idx = idxs[r];
551a8116848SStefano 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);
552a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
553a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
554a8116848SStefano Zampini     }
555a8116848SStefano Zampini     ridxs[r].rank = p;
556a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
557a8116848SStefano Zampini   }
558a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
559a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
560a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
561a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
562f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
563a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
564f0ae7da4SStefano Zampini 
565f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
566a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
567a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
568a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
569a8116848SStefano Zampini     start -= cum;
570a8116848SStefano Zampini     cum = 0;
571a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
572a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
573a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
574a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
575a8116848SStefano Zampini   }
576a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
577a8116848SStefano Zampini   /* Compress and put in indices */
578a8116848SStefano Zampini   for (r = 0; r < n; ++r)
579a8116848SStefano Zampini     if (lidxs[r] >= 0) {
580a8116848SStefano Zampini       if (work) work[len] = work[r];
581a8116848SStefano Zampini       lidxs[len++] = r;
582a8116848SStefano Zampini     }
583a8116848SStefano Zampini   if (on) *on = len;
584a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
585a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
586a8116848SStefano Zampini   PetscFunctionReturn(0);
587a8116848SStefano Zampini }
588a8116848SStefano Zampini 
589a8116848SStefano Zampini #undef __FUNCT__
590a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS"
591a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
592a8116848SStefano Zampini {
593a8116848SStefano Zampini   Mat               locmat,newlocmat;
594a8116848SStefano Zampini   Mat_IS            *newmatis;
595a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
596a8116848SStefano Zampini   Vec               rtest,ltest;
597a8116848SStefano Zampini   const PetscScalar *array;
598a8116848SStefano Zampini #endif
599a8116848SStefano Zampini   const PetscInt    *idxs;
600a8116848SStefano Zampini   PetscInt          i,m,n;
601a8116848SStefano Zampini   PetscErrorCode    ierr;
602a8116848SStefano Zampini 
603a8116848SStefano Zampini   PetscFunctionBegin;
604a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
605a8116848SStefano Zampini     PetscBool ismatis;
606a8116848SStefano Zampini 
607a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
608a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
609a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
610a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
611a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
612a8116848SStefano Zampini   }
613a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
614a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
615a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
616a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
617a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
618a8116848SStefano Zampini   for (i=0;i<n;i++) {
619a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
620a8116848SStefano Zampini   }
621a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
622a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
623a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
624a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
625a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
626fd479f66SMatthew 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]));
627a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
628a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
629a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
630a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
631a8116848SStefano Zampini   for (i=0;i<n;i++) {
632a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
633a8116848SStefano Zampini   }
634a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
635a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
636a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
637a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
638a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
639fd479f66SMatthew 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]));
640a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
641a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
642a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
643a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
644a8116848SStefano Zampini #endif
645a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
646a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
647a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
648a8116848SStefano Zampini     IS                     is;
649a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
6506dd40735SStefano Zampini     PetscInt               ll,newloc;
651a8116848SStefano Zampini     MPI_Comm               comm;
652a8116848SStefano Zampini 
653a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
654a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
655a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
656a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
657a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
658a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
659a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
660a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
661f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
662a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
6633d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
6643d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
665a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
666a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
667a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
668a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
669a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
6703d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
671a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
672a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
6733d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
674a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
675a8116848SStefano Zampini         lidxs[newloc] = i;
676a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
677a8116848SStefano Zampini       }
678a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
679a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
680a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
681a8116848SStefano Zampini     /* local is to extract local submatrix */
682a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
683a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
684a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
685a8116848SStefano Zampini       PetscBool cong;
686a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
687a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
688a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
689a8116848SStefano Zampini     }
690a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
691a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
692a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
693a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
694a8116848SStefano Zampini     } else {
695a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
696a8116848SStefano Zampini 
697a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
698a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
699f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
700a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
7013d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
702a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
703a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
704a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
705a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
706a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
7073d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
708a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
709a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
7103d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
711a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
712a8116848SStefano Zampini           lidxs[newloc] = i;
713a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
714a8116848SStefano Zampini         }
715a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
716a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
717a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
718a8116848SStefano Zampini       /* local is to extract local submatrix */
719a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
720a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
721a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
722a8116848SStefano Zampini     }
723a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
724a8116848SStefano Zampini   } else {
725a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
726a8116848SStefano Zampini   }
727a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
728a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
729a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
730a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
731a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
732a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
733a8116848SStefano Zampini   }
734a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
735a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
736a8116848SStefano Zampini   PetscFunctionReturn(0);
737a8116848SStefano Zampini }
738a8116848SStefano Zampini 
739a8116848SStefano Zampini #undef __FUNCT__
7402b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS"
741a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
7422b404112SStefano Zampini {
7432b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
7442b404112SStefano Zampini   PetscBool      ismatis;
7452b404112SStefano Zampini   PetscErrorCode ierr;
7462b404112SStefano Zampini 
7472b404112SStefano Zampini   PetscFunctionBegin;
7482b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
7492b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
7502b404112SStefano Zampini   b = (Mat_IS*)B->data;
7512b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
7522b404112SStefano Zampini   PetscFunctionReturn(0);
7532b404112SStefano Zampini }
7542b404112SStefano Zampini 
7552b404112SStefano Zampini #undef __FUNCT__
7566bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS"
757a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
7586bd84002SStefano Zampini {
759527b2640SStefano Zampini   Vec               v;
760527b2640SStefano Zampini   const PetscScalar *array;
761527b2640SStefano Zampini   PetscInt          i,n;
7626bd84002SStefano Zampini   PetscErrorCode    ierr;
7636bd84002SStefano Zampini 
7646bd84002SStefano Zampini   PetscFunctionBegin;
765527b2640SStefano Zampini   *missing = PETSC_FALSE;
766527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
767527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
768527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
769527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
770527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
771527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
772527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
773527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
774527b2640SStefano Zampini   if (d) {
775527b2640SStefano Zampini     *d = -1;
776527b2640SStefano Zampini     if (*missing) {
777527b2640SStefano Zampini       PetscInt rstart;
778527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
779527b2640SStefano Zampini       *d = i+rstart;
780527b2640SStefano Zampini     }
781527b2640SStefano Zampini   }
7826bd84002SStefano Zampini   PetscFunctionReturn(0);
7836bd84002SStefano Zampini }
7846bd84002SStefano Zampini 
7856bd84002SStefano Zampini #undef __FUNCT__
786cf0a3239SStefano Zampini #define __FUNCT__ "MatISSetUpSF_IS"
787cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
78828f4e0baSStefano Zampini {
78928f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
79028f4e0baSStefano Zampini   const PetscInt *gidxs;
7914f2d7cafSStefano Zampini   PetscInt       nleaves;
79228f4e0baSStefano Zampini   PetscErrorCode ierr;
79328f4e0baSStefano Zampini 
79428f4e0baSStefano Zampini   PetscFunctionBegin;
7954f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
79628f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
7973bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
7984f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
7994f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
8003bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
8014f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
802a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
8033d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
804a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
805a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
8063d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
807a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
8083d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
809a8116848SStefano Zampini   } else {
810a8116848SStefano Zampini     matis->csf = matis->sf;
811a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
812a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
813a8116848SStefano Zampini   }
81428f4e0baSStefano Zampini   PetscFunctionReturn(0);
81528f4e0baSStefano Zampini }
8162e1947a5SStefano Zampini 
8172e1947a5SStefano Zampini #undef __FUNCT__
8182e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
819eb82efa4SStefano Zampini /*@
820a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
821a88811baSStefano Zampini 
822a88811baSStefano Zampini    Collective on MPI_Comm
823a88811baSStefano Zampini 
824a88811baSStefano Zampini    Input Parameters:
825a88811baSStefano Zampini +  B - the matrix
826a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
827a88811baSStefano Zampini            (same value is used for all local rows)
828a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
829a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
830a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
831a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
832a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
833a88811baSStefano Zampini            the diagonal entry even if it is zero.
834a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
835a88811baSStefano Zampini            submatrix (same value is used for all local rows).
836a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
837a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
838a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
839a88811baSStefano Zampini            structure. The size of this array is equal to the number
840a88811baSStefano Zampini            of local rows, i.e 'm'.
841a88811baSStefano Zampini 
842a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
843a88811baSStefano Zampini 
844a88811baSStefano Zampini    Level: intermediate
845a88811baSStefano Zampini 
846a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
847a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
848a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
849a88811baSStefano Zampini 
850a88811baSStefano Zampini .keywords: matrix
851a88811baSStefano Zampini 
8523c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
853a88811baSStefano Zampini @*/
8542e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
8552e1947a5SStefano Zampini {
8562e1947a5SStefano Zampini   PetscErrorCode ierr;
8572e1947a5SStefano Zampini 
8582e1947a5SStefano Zampini   PetscFunctionBegin;
8592e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
8602e1947a5SStefano Zampini   PetscValidType(B,1);
8612e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
8622e1947a5SStefano Zampini   PetscFunctionReturn(0);
8632e1947a5SStefano Zampini }
8642e1947a5SStefano Zampini 
8652e1947a5SStefano Zampini #undef __FUNCT__
8662e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
8677230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
8682e1947a5SStefano Zampini {
8692e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
87028f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
8712e1947a5SStefano Zampini   PetscErrorCode ierr;
8722e1947a5SStefano Zampini 
8732e1947a5SStefano Zampini   PetscFunctionBegin;
8746c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
875cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
8764f2d7cafSStefano Zampini 
8774f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
8784f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
8794f2d7cafSStefano Zampini 
8804f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
8814f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
8824f2d7cafSStefano Zampini 
88328f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
88428f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
88528f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
88628f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
8874f2d7cafSStefano Zampini 
8884f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
88928f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
8904f2d7cafSStefano Zampini 
8914f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
89228f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
8934f2d7cafSStefano Zampini 
8944f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
89528f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
8962e1947a5SStefano Zampini   PetscFunctionReturn(0);
8972e1947a5SStefano Zampini }
898b4319ba4SBarry Smith 
899b4319ba4SBarry Smith #undef __FUNCT__
9003927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
9013927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
9023927de2eSStefano Zampini {
9033927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
9043927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
905ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
9063927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
9073927de2eSStefano Zampini   PetscInt        lrows,lcols;
9083927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
9093927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
9103927de2eSStefano Zampini   PetscBool       isdense,issbaij;
9113927de2eSStefano Zampini   PetscErrorCode  ierr;
9123927de2eSStefano Zampini 
9133927de2eSStefano Zampini   PetscFunctionBegin;
9143927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
9153927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
9163927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
9173927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
9183927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
9193927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
920ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
921ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
9227230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
923ecf5a873SStefano Zampini   } else {
924ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
925ecf5a873SStefano Zampini   }
926ecf5a873SStefano Zampini 
9273927de2eSStefano Zampini   if (issbaij) {
9283927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
9293927de2eSStefano Zampini   }
9303927de2eSStefano Zampini   /*
931ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
9323927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
9333927de2eSStefano Zampini   */
934cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
9353927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
9363927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
9373927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
9383927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
9393927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
9403927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
9413927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
9423927de2eSStefano Zampini       row_ownership[j] = i;
9433927de2eSStefano Zampini     }
9443927de2eSStefano Zampini   }
9457230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
9463927de2eSStefano Zampini 
9473927de2eSStefano Zampini   /*
9483927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
9493927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
9503927de2eSStefano Zampini   */
9513927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
9523927de2eSStefano Zampini   /* preallocation as a MATAIJ */
9533927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
9543927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
955ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
9563927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
9573927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
958ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
9593927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
9603927de2eSStefano Zampini           my_dnz[i] += 1;
9613927de2eSStefano Zampini         } else { /* offdiag block */
9623927de2eSStefano Zampini           my_onz[i] += 1;
9633927de2eSStefano Zampini         }
9643927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
9653927de2eSStefano Zampini         if (i != j) {
9663927de2eSStefano Zampini           owner = row_ownership[index_col];
9673927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
9683927de2eSStefano Zampini             my_dnz[j] += 1;
9693927de2eSStefano Zampini           } else {
9703927de2eSStefano Zampini             my_onz[j] += 1;
9713927de2eSStefano Zampini           }
9723927de2eSStefano Zampini         }
9733927de2eSStefano Zampini       }
9743927de2eSStefano Zampini     }
975bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
976bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
977bb1015c3SStefano Zampini     PetscBool      done;
978bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
979bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
980bb1015c3SStefano Zampini     jptr = jj;
981bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
982bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
983bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
984bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
985bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
986bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
987bb1015c3SStefano Zampini           my_dnz[i] += 1;
988bb1015c3SStefano Zampini         } else { /* offdiag block */
989bb1015c3SStefano Zampini           my_onz[i] += 1;
990bb1015c3SStefano Zampini         }
991bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
992bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
993bb1015c3SStefano Zampini           owner = row_ownership[index_col];
994bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
995bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
996bb1015c3SStefano Zampini           } else {
997bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
998bb1015c3SStefano Zampini           }
999bb1015c3SStefano Zampini         }
1000bb1015c3SStefano Zampini       }
1001bb1015c3SStefano Zampini     }
1002bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1003bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1004bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
10053927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
10063927de2eSStefano Zampini       const PetscInt *cols;
1007ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
10083927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
10093927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
10103927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1011ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
10123927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
10133927de2eSStefano Zampini           my_dnz[i] += 1;
10143927de2eSStefano Zampini         } else { /* offdiag block */
10153927de2eSStefano Zampini           my_onz[i] += 1;
10163927de2eSStefano Zampini         }
10173927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1018d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
10193927de2eSStefano Zampini           owner = row_ownership[index_col];
10203927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1021d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
10223927de2eSStefano Zampini           } else {
1023d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
10243927de2eSStefano Zampini           }
10253927de2eSStefano Zampini         }
10263927de2eSStefano Zampini       }
10273927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
10283927de2eSStefano Zampini     }
10293927de2eSStefano Zampini   }
1030ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1031ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
10327230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1033ecf5a873SStefano Zampini   }
10343927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1035ecf5a873SStefano Zampini 
1036ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
10373927de2eSStefano Zampini   if (maxreduce) {
10383927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
10393927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1040bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
10413927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
10423927de2eSStefano Zampini   } else {
10433927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
10443927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1045bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
10463927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
10473927de2eSStefano Zampini   }
10483927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
10493927de2eSStefano Zampini 
10503927de2eSStefano Zampini   /* Resize preallocation if overestimated */
10513927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
10523927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
10533927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
10543927de2eSStefano Zampini   }
10551670daf9Sstefano_zampini 
10561670daf9Sstefano_zampini   /* Set preallocation */
10573927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
10583927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
10593927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
10603927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
10613927de2eSStefano Zampini   }
10623927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
10633927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
10643927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
10653927de2eSStefano Zampini   if (issbaij) {
10663927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
10673927de2eSStefano Zampini   }
10683927de2eSStefano Zampini   PetscFunctionReturn(0);
10693927de2eSStefano Zampini }
10703927de2eSStefano Zampini 
10713927de2eSStefano Zampini #undef __FUNCT__
1072b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
10737230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1074b7ce53b6SStefano Zampini {
1075b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1076d9a9e74cSStefano Zampini   Mat            local_mat;
1077b7ce53b6SStefano Zampini   /* info on mat */
10783cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1079b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1080b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1081b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1082b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1083b9ed4604SStefano Zampini #endif
10847c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1085b7ce53b6SStefano Zampini   /* values insertion */
1086b7ce53b6SStefano Zampini   PetscScalar    *array;
1087b7ce53b6SStefano Zampini   /* work */
1088b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1089b7ce53b6SStefano Zampini 
1090b7ce53b6SStefano Zampini   PetscFunctionBegin;
1091b7ce53b6SStefano Zampini   /* get info from mat */
10927c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
10937c03b4e8SStefano Zampini   if (nsubdomains == 1) {
10941670daf9Sstefano_zampini     Mat            B;
10951670daf9Sstefano_zampini     IS             rows,cols;
10961670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
10971670daf9Sstefano_zampini 
10981670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
10991670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
11001670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
11011670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
11021670daf9Sstefano_zampini     ierr = MatConvert(matis->A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
11031670daf9Sstefano_zampini     ierr = MatGetSubMatrix(B,rows,cols,reuse,M);CHKERRQ(ierr);
11041670daf9Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
11051670daf9Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
11061670daf9Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
11071670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
11081670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
11097c03b4e8SStefano Zampini     PetscFunctionReturn(0);
11107c03b4e8SStefano Zampini   }
1111b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1112b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
11133cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1114b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1115b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
1116686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1117b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1118b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1119b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1120b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1121b9ed4604SStefano Zampini   lb[0] = isseqdense;
1122b9ed4604SStefano Zampini   lb[1] = isseqaij;
1123b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1124b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1125b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1126b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1127b9ed4604SStefano Zampini #endif
1128b7ce53b6SStefano Zampini 
1129b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
11303927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
11313cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
11323927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
1133b9ed4604SStefano Zampini     if (!isseqsbaij) {
1134b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1135b9ed4604SStefano Zampini     } else {
1136b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1137b9ed4604SStefano Zampini     }
11383927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1139b7ce53b6SStefano Zampini   } else {
11403cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1141b7ce53b6SStefano Zampini     /* some checks */
1142b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1143b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
11443cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
11456c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
11466c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
11476c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
11486c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
11496c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1150b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1151b7ce53b6SStefano Zampini   }
1152d9a9e74cSStefano Zampini 
1153b9ed4604SStefano Zampini   if (isseqsbaij) {
1154d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1155d9a9e74cSStefano Zampini   } else {
1156d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1157d9a9e74cSStefano Zampini     local_mat = matis->A;
1158d9a9e74cSStefano Zampini   }
1159686e3a49SStefano Zampini 
1160b7ce53b6SStefano Zampini   /* Set values */
1161ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1162b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
1163ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
1164ecf5a873SStefano Zampini 
1165ecf5a873SStefano Zampini     if (local_rows != local_cols) {
1166ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
1167ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1168ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
1169ecf5a873SStefano Zampini     } else {
1170ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
1171ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1172ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
1173ecf5a873SStefano Zampini     }
1174b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1175d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
1176ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
1177d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
1178ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
1179ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
1180ecf5a873SStefano Zampini     } else {
1181ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
1182ecf5a873SStefano Zampini     }
1183686e3a49SStefano Zampini   } else if (isseqaij) {
1184ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1185686e3a49SStefano Zampini     PetscBool done;
1186686e3a49SStefano Zampini 
1187d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1188bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1189d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1190686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1191ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1192686e3a49SStefano Zampini     }
1193d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1194bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1195d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1196686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1197ecf5a873SStefano Zampini     PetscInt i;
1198c0962df8SStefano Zampini 
1199686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1200686e3a49SStefano Zampini       PetscInt       j;
1201ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1202686e3a49SStefano Zampini 
1203ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1204ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1205ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1206686e3a49SStefano Zampini     }
1207b7ce53b6SStefano Zampini   }
1208b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1209d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1210b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1211b9ed4604SStefano Zampini   if (isseqdense) {
1212b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1213b7ce53b6SStefano Zampini   }
1214b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1215b7ce53b6SStefano Zampini }
1216b7ce53b6SStefano Zampini 
1217b7ce53b6SStefano Zampini #undef __FUNCT__
1218b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
1219b7ce53b6SStefano Zampini /*@
1220b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1221b7ce53b6SStefano Zampini 
1222b7ce53b6SStefano Zampini   Input Parameter:
1223b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1224b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1225b7ce53b6SStefano Zampini 
1226b7ce53b6SStefano Zampini   Output Parameter:
1227b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1228b7ce53b6SStefano Zampini 
1229b7ce53b6SStefano Zampini   Level: developer
1230b7ce53b6SStefano Zampini 
1231eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1232b7ce53b6SStefano Zampini 
1233b7ce53b6SStefano Zampini .seealso: MATIS
1234b7ce53b6SStefano Zampini @*/
1235b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1236b7ce53b6SStefano Zampini {
1237b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1238b7ce53b6SStefano Zampini 
1239b7ce53b6SStefano Zampini   PetscFunctionBegin;
1240b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1241b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1242b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1243b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1244b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1245b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
12466c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1247b7ce53b6SStefano Zampini   }
1248b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1249b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1250b7ce53b6SStefano Zampini }
1251b7ce53b6SStefano Zampini 
1252b7ce53b6SStefano Zampini #undef __FUNCT__
1253ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
1254ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1255ad6194a2SStefano Zampini {
1256ad6194a2SStefano Zampini   PetscErrorCode ierr;
1257ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1258ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1259ad6194a2SStefano Zampini   Mat            B,localmat;
1260ad6194a2SStefano Zampini 
1261ad6194a2SStefano Zampini   PetscFunctionBegin;
1262ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1263ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1264ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1265e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1266ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1267ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1268b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1269ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1270ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1271ad6194a2SStefano Zampini   *newmat = B;
1272ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1273ad6194a2SStefano Zampini }
1274ad6194a2SStefano Zampini 
1275ad6194a2SStefano Zampini #undef __FUNCT__
127669796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
1277a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
127869796d55SStefano Zampini {
127969796d55SStefano Zampini   PetscErrorCode ierr;
128069796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
128169796d55SStefano Zampini   PetscBool      local_sym;
128269796d55SStefano Zampini 
128369796d55SStefano Zampini   PetscFunctionBegin;
128469796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1285b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
128669796d55SStefano Zampini   PetscFunctionReturn(0);
128769796d55SStefano Zampini }
128869796d55SStefano Zampini 
128969796d55SStefano Zampini #undef __FUNCT__
129069796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
1291a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
129269796d55SStefano Zampini {
129369796d55SStefano Zampini   PetscErrorCode ierr;
129469796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
129569796d55SStefano Zampini   PetscBool      local_sym;
129669796d55SStefano Zampini 
129769796d55SStefano Zampini   PetscFunctionBegin;
129869796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1299b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
130069796d55SStefano Zampini   PetscFunctionReturn(0);
130169796d55SStefano Zampini }
130269796d55SStefano Zampini 
130369796d55SStefano Zampini #undef __FUNCT__
130445471136SStefano Zampini #define __FUNCT__ "MatIsStructurallySymmetric_IS"
130545471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
130645471136SStefano Zampini {
130745471136SStefano Zampini   PetscErrorCode ierr;
130845471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
130945471136SStefano Zampini   PetscBool      local_sym;
131045471136SStefano Zampini 
131145471136SStefano Zampini   PetscFunctionBegin;
131245471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
131345471136SStefano Zampini     *flg = PETSC_FALSE;
131445471136SStefano Zampini     PetscFunctionReturn(0);
131545471136SStefano Zampini   }
131645471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
131745471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
131845471136SStefano Zampini   PetscFunctionReturn(0);
131945471136SStefano Zampini }
132045471136SStefano Zampini 
132145471136SStefano Zampini #undef __FUNCT__
1322b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
1323a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1324b4319ba4SBarry Smith {
1325dfbe8321SBarry Smith   PetscErrorCode ierr;
1326b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1327b4319ba4SBarry Smith 
1328b4319ba4SBarry Smith   PetscFunctionBegin;
13296bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1330e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1331e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
13326bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
13336bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
13343fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1335a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1336a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1337a8116848SStefano Zampini   if (b->sf != b->csf) {
1338a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1339a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1340a8116848SStefano Zampini   }
134128f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
134228f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1343bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1344dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1345bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1346b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1347b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
13482e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1349cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1350b4319ba4SBarry Smith   PetscFunctionReturn(0);
1351b4319ba4SBarry Smith }
1352b4319ba4SBarry Smith 
1353b4319ba4SBarry Smith #undef __FUNCT__
1354b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
1355a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1356b4319ba4SBarry Smith {
1357dfbe8321SBarry Smith   PetscErrorCode ierr;
1358b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1359b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1360b4319ba4SBarry Smith 
1361b4319ba4SBarry Smith   PetscFunctionBegin;
1362b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1363e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1364e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1365b4319ba4SBarry Smith 
1366b4319ba4SBarry Smith   /* multiply the local matrix */
1367b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1368b4319ba4SBarry Smith 
1369b4319ba4SBarry Smith   /* scatter product back into global memory */
13702dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1371e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1372e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1373b4319ba4SBarry Smith   PetscFunctionReturn(0);
1374b4319ba4SBarry Smith }
1375b4319ba4SBarry Smith 
1376b4319ba4SBarry Smith #undef __FUNCT__
13772e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
1378a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
13792e74eeadSLisandro Dalcin {
1380650997f4SStefano Zampini   Vec            temp_vec;
13812e74eeadSLisandro Dalcin   PetscErrorCode ierr;
13822e74eeadSLisandro Dalcin 
13832e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1384650997f4SStefano Zampini   if (v3 != v2) {
1385650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1386650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1387650997f4SStefano Zampini   } else {
1388650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1389650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1390650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1391650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1392650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1393650997f4SStefano Zampini   }
13942e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
13952e74eeadSLisandro Dalcin }
13962e74eeadSLisandro Dalcin 
13972e74eeadSLisandro Dalcin #undef __FUNCT__
13982e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
1399a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
14002e74eeadSLisandro Dalcin {
14012e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
14022e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14032e74eeadSLisandro Dalcin 
1404e176bc59SStefano Zampini   PetscFunctionBegin;
14052e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1406e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1407e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14082e74eeadSLisandro Dalcin 
14092e74eeadSLisandro Dalcin   /* multiply the local matrix */
1410e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
14112e74eeadSLisandro Dalcin 
14122e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1413e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1414e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1415e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14162e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14172e74eeadSLisandro Dalcin }
14182e74eeadSLisandro Dalcin 
14192e74eeadSLisandro Dalcin #undef __FUNCT__
14202e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
1421a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
14222e74eeadSLisandro Dalcin {
1423650997f4SStefano Zampini   Vec            temp_vec;
14242e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14252e74eeadSLisandro Dalcin 
14262e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1427650997f4SStefano Zampini   if (v3 != v2) {
1428650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1429650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1430650997f4SStefano Zampini   } else {
1431650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1432650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1433650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1434650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1435650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1436650997f4SStefano Zampini   }
14372e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14382e74eeadSLisandro Dalcin }
14392e74eeadSLisandro Dalcin 
14402e74eeadSLisandro Dalcin #undef __FUNCT__
1441b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
1442a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1443b4319ba4SBarry Smith {
1444b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1445dfbe8321SBarry Smith   PetscErrorCode ierr;
1446b4319ba4SBarry Smith   PetscViewer    sviewer;
1447ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1448b4319ba4SBarry Smith 
1449b4319ba4SBarry Smith   PetscFunctionBegin;
1450ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1451ee2491ecSStefano Zampini   if (isascii)  {
1452ee2491ecSStefano Zampini     PetscViewerFormat format;
1453ee2491ecSStefano Zampini 
1454ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1455ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1456ee2491ecSStefano Zampini   }
1457ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
14583f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1459b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
14603f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
14616e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1462b4319ba4SBarry Smith   PetscFunctionReturn(0);
1463b4319ba4SBarry Smith }
1464b4319ba4SBarry Smith 
1465b4319ba4SBarry Smith #undef __FUNCT__
1466b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
1467a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1468b4319ba4SBarry Smith {
1469dfbe8321SBarry Smith   PetscErrorCode ierr;
1470e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1471b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1472b4319ba4SBarry Smith   IS             from,to;
1473e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1474b4319ba4SBarry Smith 
1475b4319ba4SBarry Smith   PetscFunctionBegin;
1476784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1477e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
14783bbff08aSStefano Zampini   /* Destroy any previous data */
147970cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
148070cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
14813fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1482e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1483e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
14841c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
148528f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
148628f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
14873bbff08aSStefano Zampini 
14883bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1489fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1490fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1491fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1492fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1493b4319ba4SBarry Smith 
1494b4319ba4SBarry Smith   /* Create the local matrix A */
1495e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1496e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1497e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1498e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1499f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1500e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1501e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1502e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1503ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1504ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1505b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1506b4319ba4SBarry Smith 
1507f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1508b4319ba4SBarry Smith     /* Create the local work vectors */
15093bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1510b4319ba4SBarry Smith 
1511e176bc59SStefano Zampini     /* setup the global to local scatters */
1512e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1513e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1514784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1515e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1516e176bc59SStefano Zampini     if (rmapping != cmapping) {
1517e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1518e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1519e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1520e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1521e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1522e176bc59SStefano Zampini     } else {
1523e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1524e176bc59SStefano Zampini       is->cctx = is->rctx;
1525e176bc59SStefano Zampini     }
15263fd1c9e7SStefano Zampini 
15273fd1c9e7SStefano Zampini     /* interface counter vector (local) */
15283fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
15293fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
15303fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15313fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15323fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15333fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15343fd1c9e7SStefano Zampini 
15353fd1c9e7SStefano Zampini     /* free workspace */
1536e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1537e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
15386bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
15396bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1540f26d0771SStefano Zampini   }
15419c0b00dbSStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1542b4319ba4SBarry Smith   PetscFunctionReturn(0);
1543b4319ba4SBarry Smith }
1544b4319ba4SBarry Smith 
15452e74eeadSLisandro Dalcin #undef __FUNCT__
15462e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
1547a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
15482e74eeadSLisandro Dalcin {
15492e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
15502e74eeadSLisandro Dalcin   PetscErrorCode ierr;
155197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
155297563a80SStefano Zampini   PetscInt       i,zm,zn;
155397563a80SStefano Zampini #endif
1554f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
15552e74eeadSLisandro Dalcin 
15562e74eeadSLisandro Dalcin   PetscFunctionBegin;
15572e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1558f26d0771SStefano 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);
155997563a80SStefano Zampini   /* count negative indices */
156097563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
156197563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
15622e74eeadSLisandro Dalcin #endif
156397563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
156497563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
156597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
156697563a80SStefano Zampini   /* count negative indices (should be the same as before) */
156797563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
156897563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
156997563a80SStefano 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");
157097563a80SStefano 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");
157197563a80SStefano Zampini #endif
15722e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
15732e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15742e74eeadSLisandro Dalcin }
15752e74eeadSLisandro Dalcin 
1576b4319ba4SBarry Smith #undef __FUNCT__
157797563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS"
1578a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
157997563a80SStefano Zampini {
158097563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
158197563a80SStefano Zampini   PetscErrorCode ierr;
158297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
158397563a80SStefano Zampini   PetscInt       i,zm,zn;
158497563a80SStefano Zampini #endif
1585f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
158697563a80SStefano Zampini 
158797563a80SStefano Zampini   PetscFunctionBegin;
158897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1589f26d0771SStefano 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);
159097563a80SStefano Zampini   /* count negative indices */
159197563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
159297563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
159397563a80SStefano Zampini #endif
159497563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
159597563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
159697563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
159797563a80SStefano Zampini   /* count negative indices (should be the same as before) */
159897563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
159997563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
160097563a80SStefano 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");
160197563a80SStefano 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");
160297563a80SStefano Zampini #endif
160397563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
160497563a80SStefano Zampini   PetscFunctionReturn(0);
160597563a80SStefano Zampini }
160697563a80SStefano Zampini 
160797563a80SStefano Zampini #undef __FUNCT__
1608b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
1609a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1610b4319ba4SBarry Smith {
1611dfbe8321SBarry Smith   PetscErrorCode ierr;
1612b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1613b4319ba4SBarry Smith 
1614b4319ba4SBarry Smith   PetscFunctionBegin;
1615b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1616b4319ba4SBarry Smith   PetscFunctionReturn(0);
1617b4319ba4SBarry Smith }
1618b4319ba4SBarry Smith 
1619b4319ba4SBarry Smith #undef __FUNCT__
1620f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
1621a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1622f0006bf2SLisandro Dalcin {
1623f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1624f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1625f0006bf2SLisandro Dalcin 
1626f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1627f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1628f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1629f0006bf2SLisandro Dalcin }
1630f0006bf2SLisandro Dalcin 
1631f0006bf2SLisandro Dalcin #undef __FUNCT__
1632f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private"
1633f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
16342e74eeadSLisandro Dalcin {
1635f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
16362e74eeadSLisandro Dalcin   PetscErrorCode ierr;
16372e74eeadSLisandro Dalcin 
16382e74eeadSLisandro Dalcin   PetscFunctionBegin;
1639f0ae7da4SStefano Zampini   if (!n) {
1640f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1641f0ae7da4SStefano Zampini   } else {
1642f0ae7da4SStefano Zampini     PetscInt i;
1643f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1644f0ae7da4SStefano Zampini 
1645f0ae7da4SStefano Zampini     if (columns) {
1646f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1647f0ae7da4SStefano Zampini     } else {
1648f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
16492e74eeadSLisandro Dalcin     }
1650f0ae7da4SStefano Zampini     if (diag != 0.) {
1651f0ae7da4SStefano Zampini       const PetscScalar *array;
1652f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1653f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1654f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1655f0ae7da4SStefano Zampini       }
1656f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1657f0ae7da4SStefano Zampini     }
1658f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1659f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1660f0ae7da4SStefano Zampini   }
16612e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
16622e74eeadSLisandro Dalcin }
16632e74eeadSLisandro Dalcin 
16642e74eeadSLisandro Dalcin #undef __FUNCT__
1665f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS"
1666f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
1667b4319ba4SBarry Smith {
16686e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
16696e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
16706e520ac8SStefano Zampini   PetscInt       *lrows;
1671dfbe8321SBarry Smith   PetscErrorCode ierr;
1672b4319ba4SBarry Smith 
1673b4319ba4SBarry Smith   PetscFunctionBegin;
1674f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1675f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1676f0ae7da4SStefano Zampini     PetscBool cong;
1677f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1678f0ae7da4SStefano 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");
1679f0ae7da4SStefano 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");
1680f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1681b4319ba4SBarry Smith   }
1682f0ae7da4SStefano Zampini #endif
16836e520ac8SStefano Zampini   /* get locally owned rows */
1684f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
16856e520ac8SStefano Zampini   /* fix right hand side if needed */
16866e520ac8SStefano Zampini   if (x && b) {
16876e520ac8SStefano Zampini     const PetscScalar *xx;
16886e520ac8SStefano Zampini     PetscScalar       *bb;
16892205254eSKarl Rupp 
16906e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
16916e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
16926e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
16936e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
16946e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
1695b4319ba4SBarry Smith   }
16966e520ac8SStefano Zampini   /* get rows associated to the local matrices */
16973d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
16986e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
16996e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
17006e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
17016e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
17026e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
17036e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17046e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17056e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
17066e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1707f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
17086e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
1709b4319ba4SBarry Smith   PetscFunctionReturn(0);
1710b4319ba4SBarry Smith }
1711b4319ba4SBarry Smith 
1712b4319ba4SBarry Smith #undef __FUNCT__
1713f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS"
1714f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1715b4319ba4SBarry Smith {
1716b4319ba4SBarry Smith   PetscErrorCode ierr;
1717b4319ba4SBarry Smith 
1718b4319ba4SBarry Smith   PetscFunctionBegin;
1719f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1720f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1721f0ae7da4SStefano Zampini }
1722b4319ba4SBarry Smith 
1723f0ae7da4SStefano Zampini #undef __FUNCT__
1724f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS"
1725f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1726f0ae7da4SStefano Zampini {
1727f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1728f0ae7da4SStefano Zampini 
1729f0ae7da4SStefano Zampini   PetscFunctionBegin;
1730f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1731b4319ba4SBarry Smith   PetscFunctionReturn(0);
1732b4319ba4SBarry Smith }
1733b4319ba4SBarry Smith 
1734b4319ba4SBarry Smith #undef __FUNCT__
1735b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
1736a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1737b4319ba4SBarry Smith {
1738b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1739dfbe8321SBarry Smith   PetscErrorCode ierr;
1740b4319ba4SBarry Smith 
1741b4319ba4SBarry Smith   PetscFunctionBegin;
1742b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1743b4319ba4SBarry Smith   PetscFunctionReturn(0);
1744b4319ba4SBarry Smith }
1745b4319ba4SBarry Smith 
1746b4319ba4SBarry Smith #undef __FUNCT__
1747b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
1748a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1749b4319ba4SBarry Smith {
1750b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1751dfbe8321SBarry Smith   PetscErrorCode ierr;
1752b4319ba4SBarry Smith 
1753b4319ba4SBarry Smith   PetscFunctionBegin;
1754b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1755b4319ba4SBarry Smith   PetscFunctionReturn(0);
1756b4319ba4SBarry Smith }
1757b4319ba4SBarry Smith 
1758b4319ba4SBarry Smith #undef __FUNCT__
1759b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
1760a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1761b4319ba4SBarry Smith {
1762b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1763b4319ba4SBarry Smith 
1764b4319ba4SBarry Smith   PetscFunctionBegin;
1765b4319ba4SBarry Smith   *local = is->A;
1766b4319ba4SBarry Smith   PetscFunctionReturn(0);
1767b4319ba4SBarry Smith }
1768b4319ba4SBarry Smith 
1769b4319ba4SBarry Smith #undef __FUNCT__
1770b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
1771b4319ba4SBarry Smith /*@
1772b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1773b4319ba4SBarry Smith 
1774b4319ba4SBarry Smith   Input Parameter:
1775b4319ba4SBarry Smith .  mat - the matrix
1776b4319ba4SBarry Smith 
1777b4319ba4SBarry Smith   Output Parameter:
1778eb82efa4SStefano Zampini .  local - the local matrix
1779b4319ba4SBarry Smith 
1780b4319ba4SBarry Smith   Level: advanced
1781b4319ba4SBarry Smith 
1782b4319ba4SBarry Smith   Notes:
1783b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1784b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1785b4319ba4SBarry Smith   of the MatSetValues() operation.
1786b4319ba4SBarry Smith 
1787b4319ba4SBarry Smith .seealso: MATIS
1788b4319ba4SBarry Smith @*/
17897087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1790b4319ba4SBarry Smith {
17914ac538c5SBarry Smith   PetscErrorCode ierr;
1792b4319ba4SBarry Smith 
1793b4319ba4SBarry Smith   PetscFunctionBegin;
17940700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1795b4319ba4SBarry Smith   PetscValidPointer(local,2);
17964ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1797b4319ba4SBarry Smith   PetscFunctionReturn(0);
1798b4319ba4SBarry Smith }
1799b4319ba4SBarry Smith 
18003b03a366Sstefano_zampini #undef __FUNCT__
18013b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
1802a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
18033b03a366Sstefano_zampini {
18043b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
18053b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
18063b03a366Sstefano_zampini   PetscErrorCode ierr;
18073b03a366Sstefano_zampini 
18083b03a366Sstefano_zampini   PetscFunctionBegin;
18094e4c7dbeSStefano Zampini   if (is->A) {
18103b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
18113b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1812f0ae7da4SStefano 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);
18134e4c7dbeSStefano Zampini   }
18143b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
18153b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
18163b03a366Sstefano_zampini   is->A = local;
18173b03a366Sstefano_zampini   PetscFunctionReturn(0);
18183b03a366Sstefano_zampini }
18193b03a366Sstefano_zampini 
18203b03a366Sstefano_zampini #undef __FUNCT__
18213b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
18223b03a366Sstefano_zampini /*@
1823eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
18243b03a366Sstefano_zampini 
18253b03a366Sstefano_zampini   Input Parameter:
18263b03a366Sstefano_zampini .  mat - the matrix
1827eb82efa4SStefano Zampini .  local - the local matrix
18283b03a366Sstefano_zampini 
18293b03a366Sstefano_zampini   Output Parameter:
18303b03a366Sstefano_zampini 
18313b03a366Sstefano_zampini   Level: advanced
18323b03a366Sstefano_zampini 
18333b03a366Sstefano_zampini   Notes:
18343b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
18353b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
18363b03a366Sstefano_zampini 
18373b03a366Sstefano_zampini .seealso: MATIS
18383b03a366Sstefano_zampini @*/
18393b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
18403b03a366Sstefano_zampini {
18413b03a366Sstefano_zampini   PetscErrorCode ierr;
18423b03a366Sstefano_zampini 
18433b03a366Sstefano_zampini   PetscFunctionBegin;
18443b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1845b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
18463b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
18473b03a366Sstefano_zampini   PetscFunctionReturn(0);
18483b03a366Sstefano_zampini }
18493b03a366Sstefano_zampini 
18506726f965SBarry Smith #undef __FUNCT__
18516726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
1852a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
18536726f965SBarry Smith {
18546726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
18556726f965SBarry Smith   PetscErrorCode ierr;
18566726f965SBarry Smith 
18576726f965SBarry Smith   PetscFunctionBegin;
18586726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
18596726f965SBarry Smith   PetscFunctionReturn(0);
18606726f965SBarry Smith }
18616726f965SBarry Smith 
18626726f965SBarry Smith #undef __FUNCT__
18632e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
1864a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
18652e74eeadSLisandro Dalcin {
18662e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
18672e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18682e74eeadSLisandro Dalcin 
18692e74eeadSLisandro Dalcin   PetscFunctionBegin;
18702e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
18712e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18722e74eeadSLisandro Dalcin }
18732e74eeadSLisandro Dalcin 
18742e74eeadSLisandro Dalcin #undef __FUNCT__
18752e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
1876a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
18772e74eeadSLisandro Dalcin {
18782e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
18792e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18802e74eeadSLisandro Dalcin 
18812e74eeadSLisandro Dalcin   PetscFunctionBegin;
18822e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
1883e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
18842e74eeadSLisandro Dalcin 
18852e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
18862e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
1887e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1888e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18892e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18902e74eeadSLisandro Dalcin }
18912e74eeadSLisandro Dalcin 
18922e74eeadSLisandro Dalcin #undef __FUNCT__
18936726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
1894a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
18956726f965SBarry Smith {
18966726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
18976726f965SBarry Smith   PetscErrorCode ierr;
18986726f965SBarry Smith 
18996726f965SBarry Smith   PetscFunctionBegin;
19004e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
19016726f965SBarry Smith   PetscFunctionReturn(0);
19026726f965SBarry Smith }
19036726f965SBarry Smith 
1904284134d9SBarry Smith #undef __FUNCT__
1905f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS"
1906f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
1907f26d0771SStefano Zampini {
1908f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
1909f26d0771SStefano Zampini   Mat_IS         *x;
1910f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1911f26d0771SStefano Zampini   PetscBool      ismatis;
1912f26d0771SStefano Zampini #endif
1913f26d0771SStefano Zampini   PetscErrorCode ierr;
1914f26d0771SStefano Zampini 
1915f26d0771SStefano Zampini   PetscFunctionBegin;
1916f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1917f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
1918f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
1919f26d0771SStefano Zampini #endif
1920f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
1921f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
1922f26d0771SStefano Zampini   PetscFunctionReturn(0);
1923f26d0771SStefano Zampini }
1924f26d0771SStefano Zampini 
1925f26d0771SStefano Zampini #undef __FUNCT__
1926f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS"
1927f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
1928f26d0771SStefano Zampini {
1929f26d0771SStefano Zampini   Mat                    lA;
1930f26d0771SStefano Zampini   Mat_IS                 *matis;
1931f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
1932f26d0771SStefano Zampini   IS                     is;
1933f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
1934f26d0771SStefano Zampini   PetscInt               nrg;
1935f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
1936f26d0771SStefano Zampini   PetscErrorCode         ierr;
1937f26d0771SStefano Zampini 
1938f26d0771SStefano Zampini   PetscFunctionBegin;
1939f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1940f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
1941f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
1942f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
1943f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1944f0ae7da4SStefano 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);
1945f26d0771SStefano Zampini #endif
1946f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
1947f26d0771SStefano Zampini   /* map from [0,nrl) to row */
1948f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
1949f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1950f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
1951f26d0771SStefano Zampini #else
1952f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
1953f26d0771SStefano Zampini #endif
1954f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
1955f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1956f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1957f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1958f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
1959f26d0771SStefano Zampini   /* compute new l2g map for columns */
1960f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
1961f26d0771SStefano Zampini     const PetscInt *cg,*cl;
1962f26d0771SStefano Zampini     PetscInt       ncg;
1963f26d0771SStefano Zampini     PetscInt       ncl;
1964f26d0771SStefano Zampini 
1965f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1966f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
1967f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
1968f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
1969f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1970f0ae7da4SStefano 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);
1971f26d0771SStefano Zampini #endif
1972f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
1973f26d0771SStefano Zampini     /* map from [0,ncl) to col */
1974f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
1975f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1976f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
1977f26d0771SStefano Zampini #else
1978f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
1979f26d0771SStefano Zampini #endif
1980f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
1981f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
1982f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1983f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1984f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1985f26d0771SStefano Zampini   } else {
1986f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
1987f26d0771SStefano Zampini     cl2g = rl2g;
1988f26d0771SStefano Zampini   }
1989f26d0771SStefano Zampini   /* create the MATIS submatrix */
1990f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
1991f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
1992f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1993f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
1994b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
1995f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
1996f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
1997f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1998f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
1999f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2000f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2001f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2002f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2003f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2004f26d0771SStefano Zampini   /* remove unsupported ops */
2005f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2006f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2007f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2008f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2009f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2010f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2011f26d0771SStefano Zampini   PetscFunctionReturn(0);
2012f26d0771SStefano Zampini }
2013f26d0771SStefano Zampini 
2014f26d0771SStefano Zampini #undef __FUNCT__
2015284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
2016284134d9SBarry Smith /*@
20173c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2018284134d9SBarry Smith        process but not across processes.
2019284134d9SBarry Smith 
2020284134d9SBarry Smith    Input Parameters:
2021284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2022e176bc59SStefano Zampini .     bs      - block size of the matrix
2023df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2024e176bc59SStefano Zampini .     rmap    - local to global map for rows
2025e176bc59SStefano Zampini -     cmap    - local to global map for cols
2026284134d9SBarry Smith 
2027284134d9SBarry Smith    Output Parameter:
2028284134d9SBarry Smith .    A - the resulting matrix
2029284134d9SBarry Smith 
20308e6c10adSSatish Balay    Level: advanced
20318e6c10adSSatish Balay 
20323c212e90SHong Zhang    Notes: See MATIS for more details.
20336fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
20346fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
20353c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2036284134d9SBarry Smith 
2037284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2038284134d9SBarry Smith @*/
2039e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2040284134d9SBarry Smith {
2041284134d9SBarry Smith   PetscErrorCode ierr;
2042284134d9SBarry Smith 
2043284134d9SBarry Smith   PetscFunctionBegin;
20446fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2045284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
20466fdf41d1SStefano Zampini   if (bs > 0) {
2047d3ee2243SStefano Zampini     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
20486fdf41d1SStefano Zampini   }
2049284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
2050284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2051e176bc59SStefano Zampini   if (rmap && cmap) {
2052e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2053e176bc59SStefano Zampini   } else if (!rmap) {
2054e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2055e176bc59SStefano Zampini   } else {
2056e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2057e176bc59SStefano Zampini   }
2058284134d9SBarry Smith   PetscFunctionReturn(0);
2059284134d9SBarry Smith }
2060284134d9SBarry Smith 
2061b4319ba4SBarry Smith /*MC
2062f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2063b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2064b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2065b4319ba4SBarry Smith    product is handled "implicitly".
2066b4319ba4SBarry Smith 
2067b4319ba4SBarry Smith    Operations Provided:
20686726f965SBarry Smith +  MatMult()
20692e74eeadSLisandro Dalcin .  MatMultAdd()
20702e74eeadSLisandro Dalcin .  MatMultTranspose()
20712e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
20726726f965SBarry Smith .  MatZeroEntries()
20736726f965SBarry Smith .  MatSetOption()
20742e74eeadSLisandro Dalcin .  MatZeroRows()
20752e74eeadSLisandro Dalcin .  MatSetValues()
207697563a80SStefano Zampini .  MatSetValuesBlocked()
20776726f965SBarry Smith .  MatSetValuesLocal()
207897563a80SStefano Zampini .  MatSetValuesBlockedLocal()
20792e74eeadSLisandro Dalcin .  MatScale()
20802e74eeadSLisandro Dalcin .  MatGetDiagonal()
20812b404112SStefano Zampini .  MatMissingDiagonal()
20822b404112SStefano Zampini .  MatDuplicate()
20832b404112SStefano Zampini .  MatCopy()
2084f26d0771SStefano Zampini .  MatAXPY()
2085f26d0771SStefano Zampini .  MatGetSubMatrix()
2086f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2087d7f69cd0SStefano Zampini .  MatTranspose()
20886726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2089b4319ba4SBarry Smith 
2090b4319ba4SBarry Smith    Options Database Keys:
2091b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2092b4319ba4SBarry Smith 
2093b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
2094b4319ba4SBarry Smith 
2095b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2096b4319ba4SBarry Smith 
2097b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2098eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2099b4319ba4SBarry Smith 
2100b4319ba4SBarry Smith   Level: advanced
2101b4319ba4SBarry Smith 
2102f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2103b4319ba4SBarry Smith 
2104b4319ba4SBarry Smith M*/
2105b4319ba4SBarry Smith 
2106b4319ba4SBarry Smith #undef __FUNCT__
2107b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
21088cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2109b4319ba4SBarry Smith {
2110dfbe8321SBarry Smith   PetscErrorCode ierr;
2111b4319ba4SBarry Smith   Mat_IS         *b;
2112b4319ba4SBarry Smith 
2113b4319ba4SBarry Smith   PetscFunctionBegin;
2114b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2115b4319ba4SBarry Smith   A->data = (void*)b;
2116b4319ba4SBarry Smith 
2117e176bc59SStefano Zampini   /* matrix ops */
2118e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2119b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
21202e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
21212e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
21222e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2123b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2124b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
21252e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
212698921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2127b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2128f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
21292e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2130f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2131b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2132b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2133b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
21346726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
21352e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
21362e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
21376726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
213869796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
213969796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
214045471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2141ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
21426bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
21432b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2144659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
2145a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
2146f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
21473fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
21483fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2149d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
2150b4319ba4SBarry Smith 
2151b7ce53b6SStefano Zampini   /* special MATIS functions */
2152bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
2153bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2154b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
21552e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2156cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
215717667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2158b4319ba4SBarry Smith   PetscFunctionReturn(0);
2159b4319ba4SBarry Smith }
2160