xref: /petsc/src/mat/impls/is/matis.c (revision 5b003df003d025fc2d803b911962440b35d10dc0)
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__
17*5b003df0Sstefano_zampini #define __FUNCT__ "MatISContainerDestroyFields_Private"
18*5b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
19*5b003df0Sstefano_zampini {
20*5b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
21*5b003df0Sstefano_zampini   PetscInt         i;
22*5b003df0Sstefano_zampini   PetscErrorCode   ierr;
23*5b003df0Sstefano_zampini 
24*5b003df0Sstefano_zampini   PetscFunctionBeginUser;
25*5b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
26*5b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
27*5b003df0Sstefano_zampini   }
28*5b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
29*5b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
30*5b003df0Sstefano_zampini   }
31*5b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
32*5b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
33*5b003df0Sstefano_zampini   PetscFunctionReturn(0);
34*5b003df0Sstefano_zampini }
35*5b003df0Sstefano_zampini 
36*5b003df0Sstefano_zampini #undef __FUNCT__
37*5b003df0Sstefano_zampini #define __FUNCT__ "MatISContainerDestroyArray_Private"
38*5b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyArray_Private(void *ptr)
396989cf23SStefano Zampini {
406989cf23SStefano Zampini   PetscErrorCode ierr;
416989cf23SStefano Zampini 
426989cf23SStefano Zampini   PetscFunctionBeginUser;
436989cf23SStefano Zampini   ierr = PetscFree(ptr);CHKERRQ(ierr);
446989cf23SStefano Zampini   PetscFunctionReturn(0);
456989cf23SStefano Zampini }
466989cf23SStefano Zampini 
476989cf23SStefano Zampini #undef __FUNCT__
486989cf23SStefano Zampini #define __FUNCT__ "MatConvert_MPIAIJ_IS"
496989cf23SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
506989cf23SStefano Zampini {
516989cf23SStefano Zampini   Mat_MPIAIJ             *aij  = (Mat_MPIAIJ*)A->data;
526989cf23SStefano Zampini   Mat_SeqAIJ             *diag = (Mat_SeqAIJ*)(aij->A->data);
536989cf23SStefano Zampini   Mat_SeqAIJ             *offd = (Mat_SeqAIJ*)(aij->B->data);
546989cf23SStefano Zampini   Mat                    lA;
556989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
566989cf23SStefano Zampini   IS                     is;
576989cf23SStefano Zampini   MPI_Comm               comm;
586989cf23SStefano Zampini   void                   *ptrs[2];
596989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
606989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
616989cf23SStefano Zampini   PetscInt               *di,*dj,*oi,*oj;
626989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
63e363d98aSStefano Zampini   PetscInt               lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
646989cf23SStefano Zampini   PetscErrorCode         ierr;
656989cf23SStefano Zampini 
666989cf23SStefano Zampini   PetscFunctionBeginUser;
676989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
686989cf23SStefano Zampini   if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present");
696989cf23SStefano Zampini 
706989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
716989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
726989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
736989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
746989cf23SStefano Zampini   di   = diag->i;
756989cf23SStefano Zampini   dj   = diag->j;
766989cf23SStefano Zampini   dd   = diag->a;
776989cf23SStefano Zampini   oc   = aij->B->cmap->n;
786989cf23SStefano Zampini   oi   = offd->i;
796989cf23SStefano Zampini   oj   = offd->j;
806989cf23SStefano Zampini   od   = offd->a;
816989cf23SStefano Zampini   nnz  = diag->i[dr] + offd->i[dr];
826989cf23SStefano Zampini 
836989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
846989cf23SStefano Zampini   ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
856989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
866989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
87e363d98aSStefano Zampini   if (dr) {
886989cf23SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
896989cf23SStefano Zampini     for (i=0; i<dc; i++) aux[i]    = i+stc;
906989cf23SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i];
916989cf23SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
92e363d98aSStefano Zampini     lc   = dc+oc;
93e363d98aSStefano Zampini   } else {
94e363d98aSStefano Zampini     ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
95e363d98aSStefano Zampini     lc   = 0;
96e363d98aSStefano Zampini   }
976989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
986989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
996989cf23SStefano Zampini 
1006989cf23SStefano Zampini   /* create MATIS object */
1016989cf23SStefano Zampini   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1026989cf23SStefano Zampini   ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1036989cf23SStefano Zampini   ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1046989cf23SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1056989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1066989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1076989cf23SStefano Zampini 
1086989cf23SStefano Zampini   /* merge local matrices */
1096989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
1106989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
1116989cf23SStefano Zampini   ii   = aux;
1126989cf23SStefano Zampini   jj   = aux+dr+1;
1136989cf23SStefano Zampini   aa   = data;
1146989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
1156989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
1166989cf23SStefano Zampini   {
1176989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
1186989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
1196989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
1206989cf23SStefano Zampini   }
1216989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
1226989cf23SStefano Zampini   ii   = aux;
1236989cf23SStefano Zampini   jj   = aux+dr+1;
1246989cf23SStefano Zampini   aa   = data;
125e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
1266989cf23SStefano Zampini 
1276989cf23SStefano Zampini   /* create containers to destroy the data */
1286989cf23SStefano Zampini   ptrs[0] = aux;
1296989cf23SStefano Zampini   ptrs[1] = data;
1306989cf23SStefano Zampini   for (i=0; i<2; i++) {
1316989cf23SStefano Zampini     PetscContainer c;
1326989cf23SStefano Zampini 
1336989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
1346989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
135*5b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyArray_Private);CHKERRQ(ierr);
1366989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
1376989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
1386989cf23SStefano Zampini   }
1396989cf23SStefano Zampini 
1406989cf23SStefano Zampini   /* finalize matrix */
1416989cf23SStefano Zampini   ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
1426989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
1436989cf23SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1446989cf23SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1456989cf23SStefano Zampini   PetscFunctionReturn(0);
1466989cf23SStefano Zampini }
1476989cf23SStefano Zampini 
1486989cf23SStefano Zampini #undef __FUNCT__
149cf0a3239SStefano Zampini #define __FUNCT__ "MatISSetUpSF"
150cf0a3239SStefano Zampini /*@
1513d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
152cf0a3239SStefano Zampini 
153cf0a3239SStefano Zampini    Collective on MPI_Comm
154cf0a3239SStefano Zampini 
155cf0a3239SStefano Zampini    Input Parameters:
156cf0a3239SStefano Zampini +  A - the matrix
157cf0a3239SStefano Zampini 
158cf0a3239SStefano Zampini    Level: advanced
159cf0a3239SStefano Zampini 
1603d996552SStefano Zampini    Notes: This function does not need to be called by the user.
161cf0a3239SStefano Zampini 
162cf0a3239SStefano Zampini .keywords: matrix
163cf0a3239SStefano Zampini 
164cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
165cf0a3239SStefano Zampini @*/
166cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
167cf0a3239SStefano Zampini {
168cf0a3239SStefano Zampini   PetscErrorCode ierr;
169cf0a3239SStefano Zampini 
170cf0a3239SStefano Zampini   PetscFunctionBegin;
171cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
172cf0a3239SStefano Zampini   PetscValidType(A,1);
173cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
174cf0a3239SStefano Zampini   PetscFunctionReturn(0);
175cf0a3239SStefano Zampini }
176a72627d2SStefano Zampini 
17728f4e0baSStefano Zampini #undef __FUNCT__
1785e3038f0Sstefano_zampini #define __FUNCT__ "MatConvert_Nest_IS"
1795e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1805e3038f0Sstefano_zampini {
1815e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
1825e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
1835e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
1845e3038f0Sstefano_zampini   MPI_Comm               comm;
185*5b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
186*5b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
1875e3038f0Sstefano_zampini   PetscBool              convert,lreuse;
1885e3038f0Sstefano_zampini   PetscErrorCode         ierr;
1895e3038f0Sstefano_zampini 
1905e3038f0Sstefano_zampini   PetscFunctionBeginUser;
1915e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
1925e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
1935e3038f0Sstefano_zampini   rnest  = NULL;
1945e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
1955e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
1965e3038f0Sstefano_zampini 
1975e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1985e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
1995e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
2005e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
2015e3038f0Sstefano_zampini     if (isnest) {
2025e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
2035e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
2045e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
2055e3038f0Sstefano_zampini     }
2065e3038f0Sstefano_zampini   }
2075e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
208*5b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
2095e3038f0Sstefano_zampini   ierr = PetscCalloc5(nr,&isrow,nc,&iscol,
2105e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
2115e3038f0Sstefano_zampini                       nr*nc,&snest);CHKERRQ(ierr);
2125e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
2135e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2145e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2155e3038f0Sstefano_zampini       PetscBool ismatis;
2165e3038f0Sstefano_zampini       PetscInt  l1,l2,ij=i*nc+j;
2175e3038f0Sstefano_zampini 
2185e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
2195e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2205e3038f0Sstefano_zampini 
2215e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
2225e3038f0Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
2235e3038f0Sstefano_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);
2245e3038f0Sstefano_zampini 
2255e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
2265e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
2275e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
2285e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
2295e3038f0Sstefano_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);
2305e3038f0Sstefano_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);
2315e3038f0Sstefano_zampini       lr[i] = l1;
2325e3038f0Sstefano_zampini       lc[j] = l2;
2335e3038f0Sstefano_zampini 
2345e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
2355e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
2365e3038f0Sstefano_zampini     }
2375e3038f0Sstefano_zampini   }
2385e3038f0Sstefano_zampini 
2395e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
2405e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
2415e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2425e3038f0Sstefano_zampini     rl2g = NULL;
2435e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2445e3038f0Sstefano_zampini       PetscInt n1,n2;
2455e3038f0Sstefano_zampini 
2465e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2475e3038f0Sstefano_zampini       ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
2485e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2495e3038f0Sstefano_zampini       if (!n1) continue;
2505e3038f0Sstefano_zampini       if (!rl2g) {
2515e3038f0Sstefano_zampini         rl2g = cl2g;
2525e3038f0Sstefano_zampini       } else {
2535e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2545e3038f0Sstefano_zampini         PetscBool      same;
2555e3038f0Sstefano_zampini 
2565e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2575e3038f0Sstefano_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);
2585e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2595e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2605e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2615e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2625e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2635e3038f0Sstefano_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);
2645e3038f0Sstefano_zampini       }
2655e3038f0Sstefano_zampini     }
2665e3038f0Sstefano_zampini   }
2675e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
2685e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
2695e3038f0Sstefano_zampini     rl2g = NULL;
2705e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
2715e3038f0Sstefano_zampini       PetscInt n1,n2;
2725e3038f0Sstefano_zampini 
2735e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
2745e3038f0Sstefano_zampini       ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
2755e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2765e3038f0Sstefano_zampini       if (!n1) continue;
2775e3038f0Sstefano_zampini       if (!rl2g) {
2785e3038f0Sstefano_zampini         rl2g = cl2g;
2795e3038f0Sstefano_zampini       } else {
2805e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2815e3038f0Sstefano_zampini         PetscBool      same;
2825e3038f0Sstefano_zampini 
2835e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2845e3038f0Sstefano_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);
2855e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2865e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2875e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2885e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2895e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2905e3038f0Sstefano_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);
2915e3038f0Sstefano_zampini       }
2925e3038f0Sstefano_zampini     }
2935e3038f0Sstefano_zampini   }
2945e3038f0Sstefano_zampini #endif
2955e3038f0Sstefano_zampini 
2965e3038f0Sstefano_zampini   B = NULL;
2975e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
298*5b003df0Sstefano_zampini     PetscInt stl;
299*5b003df0Sstefano_zampini 
3005e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
3015e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
3025e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
303*5b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
3045e3038f0Sstefano_zampini       Mat            usedmat;
3055e3038f0Sstefano_zampini       Mat_IS         *matis;
3065e3038f0Sstefano_zampini       const PetscInt *idxs;
3075e3038f0Sstefano_zampini 
3085e3038f0Sstefano_zampini       /* local IS for local NEST */
309*5b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
3105e3038f0Sstefano_zampini 
3115e3038f0Sstefano_zampini       /* l2gmap */
3125e3038f0Sstefano_zampini       j = 0;
3135e3038f0Sstefano_zampini       usedmat = nest[i][j];
3145e3038f0Sstefano_zampini       while (!usedmat && j < nc) usedmat = nest[i][j++];
31582d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3165e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3175e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
3185e3038f0Sstefano_zampini       ierr  = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3195e3038f0Sstefano_zampini       ierr  = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3205e3038f0Sstefano_zampini       ierr  = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
3215e3038f0Sstefano_zampini       stl  += lr[i];
3225e3038f0Sstefano_zampini     }
3235e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
3245e3038f0Sstefano_zampini 
3255e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
3265e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
3275e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
328*5b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
3295e3038f0Sstefano_zampini       Mat            usedmat;
3305e3038f0Sstefano_zampini       Mat_IS         *matis;
3315e3038f0Sstefano_zampini       const PetscInt *idxs;
3325e3038f0Sstefano_zampini 
3335e3038f0Sstefano_zampini       /* local IS for local NEST */
334*5b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
3355e3038f0Sstefano_zampini 
3365e3038f0Sstefano_zampini       /* l2gmap */
3375e3038f0Sstefano_zampini       j = 0;
3385e3038f0Sstefano_zampini       usedmat = nest[j][i];
3395e3038f0Sstefano_zampini       while (!usedmat && j < nr) usedmat = nest[j++][i];
34082d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3415e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3425e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
3435e3038f0Sstefano_zampini       ierr  = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3445e3038f0Sstefano_zampini       ierr  = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3455e3038f0Sstefano_zampini       ierr  = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
3465e3038f0Sstefano_zampini       stl  += lc[i];
3475e3038f0Sstefano_zampini     }
3485e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
3495e3038f0Sstefano_zampini 
3505e3038f0Sstefano_zampini     /* Create MATIS */
3515e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
3525e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
3535e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
3545e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
3555e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
3565e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
3575e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3585e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3595e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
3605e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
3615e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
3625e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3635e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3645e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
3655e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
3665e3038f0Sstefano_zampini     } else {
3675e3038f0Sstefano_zampini       *newmat = B;
3685e3038f0Sstefano_zampini     }
3695e3038f0Sstefano_zampini   } else {
3705e3038f0Sstefano_zampini     if (lreuse) {
3715e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
3725e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
3735e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
3745e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
3755e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
3765e3038f0Sstefano_zampini           }
3775e3038f0Sstefano_zampini         }
3785e3038f0Sstefano_zampini       }
3795e3038f0Sstefano_zampini     } else {
380*5b003df0Sstefano_zampini       PetscInt stl;
381*5b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
382*5b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
383*5b003df0Sstefano_zampini         stl  += lr[i];
3845e3038f0Sstefano_zampini       }
385*5b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
386*5b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
387*5b003df0Sstefano_zampini         stl  += lc[i];
3885e3038f0Sstefano_zampini       }
3895e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
3905e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
3915e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
3925e3038f0Sstefano_zampini     }
3935e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3945e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3955e3038f0Sstefano_zampini   }
3965e3038f0Sstefano_zampini 
397*5b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
398*5b003df0Sstefano_zampini   convert = PETSC_FALSE;
399*5b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
400*5b003df0Sstefano_zampini   if (convert) {
401*5b003df0Sstefano_zampini     Mat              M;
402*5b003df0Sstefano_zampini     MatISLocalFields lf;
403*5b003df0Sstefano_zampini     PetscContainer   c;
404*5b003df0Sstefano_zampini 
405*5b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
406*5b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
407*5b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
408*5b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
409*5b003df0Sstefano_zampini 
410*5b003df0Sstefano_zampini     /* attach local fields to the matrix */
411*5b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
412*5b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
413*5b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
414*5b003df0Sstefano_zampini       PetscInt n,st;
415*5b003df0Sstefano_zampini 
416*5b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
417*5b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
418*5b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
419*5b003df0Sstefano_zampini     }
420*5b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
421*5b003df0Sstefano_zampini       PetscInt n,st;
422*5b003df0Sstefano_zampini 
423*5b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
424*5b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
425*5b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
426*5b003df0Sstefano_zampini     }
427*5b003df0Sstefano_zampini     lf->nr = nr;
428*5b003df0Sstefano_zampini     lf->nc = nc;
429*5b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
430*5b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
431*5b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
432*5b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
433*5b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
434*5b003df0Sstefano_zampini   }
435*5b003df0Sstefano_zampini 
4365e3038f0Sstefano_zampini   /* Free workspace */
4375e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4385e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
4395e3038f0Sstefano_zampini   }
4405e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
4415e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
4425e3038f0Sstefano_zampini   }
4435e3038f0Sstefano_zampini   ierr = PetscFree5(isrow,iscol,islrow,islcol,snest);CHKERRQ(ierr);
444*5b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
4455e3038f0Sstefano_zampini   PetscFunctionReturn(0);
4465e3038f0Sstefano_zampini }
4475e3038f0Sstefano_zampini 
4485e3038f0Sstefano_zampini #undef __FUNCT__
449d7f69cd0SStefano Zampini #define __FUNCT__ "MatTranspose_IS"
450d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
451d7f69cd0SStefano Zampini {
452d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
453d7f69cd0SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
454d7f69cd0SStefano Zampini   PetscBool              notset = PETSC_FALSE,cong = PETSC_TRUE;
455d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
456d7f69cd0SStefano Zampini 
457d7f69cd0SStefano Zampini   PetscFunctionBegin;
458d7f69cd0SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
459d7f69cd0SStefano Zampini     PetscBool rcong,ccong;
460d7f69cd0SStefano Zampini 
461d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr);
462d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr);
463fa520230SStefano Zampini     cong = (PetscBool)(rcong || ccong);
464d7f69cd0SStefano Zampini   }
465d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) {
466d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
467d7f69cd0SStefano Zampini   } else {
468d7f69cd0SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,&notset);CHKERRQ(ierr);
469d7f69cd0SStefano Zampini     C = *B;
470d7f69cd0SStefano Zampini   }
471d7f69cd0SStefano Zampini 
472d7f69cd0SStefano Zampini   if (!notset) {
473d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
474d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
475d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
476d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
477d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
478d7f69cd0SStefano Zampini   }
479d7f69cd0SStefano Zampini 
480d7f69cd0SStefano Zampini   /* perform local transposition */
481d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
482d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
483d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
484d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
485d7f69cd0SStefano Zampini 
486d7f69cd0SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
487d7f69cd0SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
488d7f69cd0SStefano Zampini 
489d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
490d7f69cd0SStefano Zampini     if (!cong) {
491d7f69cd0SStefano Zampini       ierr = MatDestroy(B);CHKERRQ(ierr);
492d7f69cd0SStefano Zampini     }
493d7f69cd0SStefano Zampini     *B = C;
494d7f69cd0SStefano Zampini   } else {
495d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
496d7f69cd0SStefano Zampini   }
497d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
498d7f69cd0SStefano Zampini }
499d7f69cd0SStefano Zampini 
500d7f69cd0SStefano Zampini #undef __FUNCT__
5013fd1c9e7SStefano Zampini #define __FUNCT__ "MatDiagonalSet_IS"
5023fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
5033fd1c9e7SStefano Zampini {
5043fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
5053fd1c9e7SStefano Zampini   PetscErrorCode ierr;
5063fd1c9e7SStefano Zampini 
5073fd1c9e7SStefano Zampini   PetscFunctionBegin;
5083fd1c9e7SStefano Zampini   if (!D) { /* this code branch is used by MatShift_IS */
5093fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
5103fd1c9e7SStefano Zampini   } else {
5113fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5123fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5133fd1c9e7SStefano Zampini   }
5143fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
5153fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
5163fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
5173fd1c9e7SStefano Zampini }
5183fd1c9e7SStefano Zampini 
5193fd1c9e7SStefano Zampini #undef __FUNCT__
5203fd1c9e7SStefano Zampini #define __FUNCT__ "MatShift_IS"
5213fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
5223fd1c9e7SStefano Zampini {
5233fd1c9e7SStefano Zampini   PetscErrorCode ierr;
5243fd1c9e7SStefano Zampini 
5253fd1c9e7SStefano Zampini   PetscFunctionBegin;
5263fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
5273fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
5283fd1c9e7SStefano Zampini }
5293fd1c9e7SStefano Zampini 
5303fd1c9e7SStefano Zampini #undef __FUNCT__
531f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS"
532f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
533f26d0771SStefano Zampini {
534f26d0771SStefano Zampini   PetscErrorCode ierr;
535f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
536f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
537f26d0771SStefano Zampini 
538f26d0771SStefano Zampini   PetscFunctionBegin;
539f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
540f26d0771SStefano 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);
541f26d0771SStefano Zampini #endif
542f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
543f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
544f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
545f26d0771SStefano Zampini   PetscFunctionReturn(0);
546f26d0771SStefano Zampini }
547f26d0771SStefano Zampini 
548f26d0771SStefano Zampini #undef __FUNCT__
549f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS"
550f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
551f26d0771SStefano Zampini {
552f26d0771SStefano Zampini   PetscErrorCode ierr;
553f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
554f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
555f26d0771SStefano Zampini 
556f26d0771SStefano Zampini   PetscFunctionBegin;
557f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
558f26d0771SStefano 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);
559f26d0771SStefano Zampini #endif
560f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
561f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
562f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
563f26d0771SStefano Zampini   PetscFunctionReturn(0);
564f26d0771SStefano Zampini }
565f26d0771SStefano Zampini 
566f26d0771SStefano Zampini #undef __FUNCT__
567a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private"
568f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
569a8116848SStefano Zampini {
570a8116848SStefano Zampini   PetscInt      *owners = map->range;
571a8116848SStefano Zampini   PetscInt       n      = map->n;
572a8116848SStefano Zampini   PetscSF        sf;
573a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
574a8116848SStefano Zampini   PetscSFNode   *ridxs;
575a8116848SStefano Zampini   PetscMPIInt    rank;
576a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
577a8116848SStefano Zampini   PetscErrorCode ierr;
578a8116848SStefano Zampini 
579a8116848SStefano Zampini   PetscFunctionBegin;
580a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
581a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
582a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
583a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
584a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
585a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
586a8116848SStefano Zampini     const PetscInt idx = idxs[r];
587a8116848SStefano 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);
588a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
589a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
590a8116848SStefano Zampini     }
591a8116848SStefano Zampini     ridxs[r].rank = p;
592a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
593a8116848SStefano Zampini   }
594a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
595a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
596a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
597a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
598f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
599a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
600f0ae7da4SStefano Zampini 
601f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
602a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
603a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
604a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
605a8116848SStefano Zampini     start -= cum;
606a8116848SStefano Zampini     cum = 0;
607a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
608a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
609a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
610a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
611a8116848SStefano Zampini   }
612a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
613a8116848SStefano Zampini   /* Compress and put in indices */
614a8116848SStefano Zampini   for (r = 0; r < n; ++r)
615a8116848SStefano Zampini     if (lidxs[r] >= 0) {
616a8116848SStefano Zampini       if (work) work[len] = work[r];
617a8116848SStefano Zampini       lidxs[len++] = r;
618a8116848SStefano Zampini     }
619a8116848SStefano Zampini   if (on) *on = len;
620a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
621a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
622a8116848SStefano Zampini   PetscFunctionReturn(0);
623a8116848SStefano Zampini }
624a8116848SStefano Zampini 
625a8116848SStefano Zampini #undef __FUNCT__
626a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS"
627a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
628a8116848SStefano Zampini {
629a8116848SStefano Zampini   Mat               locmat,newlocmat;
630a8116848SStefano Zampini   Mat_IS            *newmatis;
631a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
632a8116848SStefano Zampini   Vec               rtest,ltest;
633a8116848SStefano Zampini   const PetscScalar *array;
634a8116848SStefano Zampini #endif
635a8116848SStefano Zampini   const PetscInt    *idxs;
636a8116848SStefano Zampini   PetscInt          i,m,n;
637a8116848SStefano Zampini   PetscErrorCode    ierr;
638a8116848SStefano Zampini 
639a8116848SStefano Zampini   PetscFunctionBegin;
640a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
641a8116848SStefano Zampini     PetscBool ismatis;
642a8116848SStefano Zampini 
643a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
644a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
645a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
646a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
647a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
648a8116848SStefano Zampini   }
649a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
650a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
651a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
652a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
653a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
654a8116848SStefano Zampini   for (i=0;i<n;i++) {
655a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
656a8116848SStefano Zampini   }
657a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
658a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
659a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
660a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
661a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
662fd479f66SMatthew 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]));
663a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
664a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
665a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
666a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
667a8116848SStefano Zampini   for (i=0;i<n;i++) {
668a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
669a8116848SStefano Zampini   }
670a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
671a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
672a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
673a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
674a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
675fd479f66SMatthew 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]));
676a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
677a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
678a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
679a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
680a8116848SStefano Zampini #endif
681a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
682a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
683a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
684a8116848SStefano Zampini     IS                     is;
685a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
6866dd40735SStefano Zampini     PetscInt               ll,newloc;
687a8116848SStefano Zampini     MPI_Comm               comm;
688a8116848SStefano Zampini 
689a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
690a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
691a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
692a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
693a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
694a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
695a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
696a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
697f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
698a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
6993d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
7003d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
701a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
702a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
703a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
704a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
705a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
7063d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
707a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
708a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
7093d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
710a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
711a8116848SStefano Zampini         lidxs[newloc] = i;
712a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
713a8116848SStefano Zampini       }
714a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
715a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
716a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
717a8116848SStefano Zampini     /* local is to extract local submatrix */
718a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
719a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
720a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
721a8116848SStefano Zampini       PetscBool cong;
722a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
723a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
724a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
725a8116848SStefano Zampini     }
726a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
727a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
728a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
729a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
730a8116848SStefano Zampini     } else {
731a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
732a8116848SStefano Zampini 
733a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
734a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
735f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
736a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
7373d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
738a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
739a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
740a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
741a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
742a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
7433d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
744a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
745a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
7463d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
747a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
748a8116848SStefano Zampini           lidxs[newloc] = i;
749a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
750a8116848SStefano Zampini         }
751a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
752a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
753a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
754a8116848SStefano Zampini       /* local is to extract local submatrix */
755a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
756a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
757a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
758a8116848SStefano Zampini     }
759a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
760a8116848SStefano Zampini   } else {
761a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
762a8116848SStefano Zampini   }
763a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
764a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
765a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
766a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
767a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
768a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
769a8116848SStefano Zampini   }
770a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
771a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
772a8116848SStefano Zampini   PetscFunctionReturn(0);
773a8116848SStefano Zampini }
774a8116848SStefano Zampini 
775a8116848SStefano Zampini #undef __FUNCT__
7762b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS"
777a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
7782b404112SStefano Zampini {
7792b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
7802b404112SStefano Zampini   PetscBool      ismatis;
7812b404112SStefano Zampini   PetscErrorCode ierr;
7822b404112SStefano Zampini 
7832b404112SStefano Zampini   PetscFunctionBegin;
7842b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
7852b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
7862b404112SStefano Zampini   b = (Mat_IS*)B->data;
7872b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
7882b404112SStefano Zampini   PetscFunctionReturn(0);
7892b404112SStefano Zampini }
7902b404112SStefano Zampini 
7912b404112SStefano Zampini #undef __FUNCT__
7926bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS"
793a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
7946bd84002SStefano Zampini {
795527b2640SStefano Zampini   Vec               v;
796527b2640SStefano Zampini   const PetscScalar *array;
797527b2640SStefano Zampini   PetscInt          i,n;
7986bd84002SStefano Zampini   PetscErrorCode    ierr;
7996bd84002SStefano Zampini 
8006bd84002SStefano Zampini   PetscFunctionBegin;
801527b2640SStefano Zampini   *missing = PETSC_FALSE;
802527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
803527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
804527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
805527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
806527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
807527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
808527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
809527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
810527b2640SStefano Zampini   if (d) {
811527b2640SStefano Zampini     *d = -1;
812527b2640SStefano Zampini     if (*missing) {
813527b2640SStefano Zampini       PetscInt rstart;
814527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
815527b2640SStefano Zampini       *d = i+rstart;
816527b2640SStefano Zampini     }
817527b2640SStefano Zampini   }
8186bd84002SStefano Zampini   PetscFunctionReturn(0);
8196bd84002SStefano Zampini }
8206bd84002SStefano Zampini 
8216bd84002SStefano Zampini #undef __FUNCT__
822cf0a3239SStefano Zampini #define __FUNCT__ "MatISSetUpSF_IS"
823cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
82428f4e0baSStefano Zampini {
82528f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
82628f4e0baSStefano Zampini   const PetscInt *gidxs;
8274f2d7cafSStefano Zampini   PetscInt       nleaves;
82828f4e0baSStefano Zampini   PetscErrorCode ierr;
82928f4e0baSStefano Zampini 
83028f4e0baSStefano Zampini   PetscFunctionBegin;
8314f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
83228f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
8333bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
8344f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
8354f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
8363bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
8374f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
838a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
8393d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
840a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
841a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
8423d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
843a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
8443d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
845a8116848SStefano Zampini   } else {
846a8116848SStefano Zampini     matis->csf = matis->sf;
847a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
848a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
849a8116848SStefano Zampini   }
85028f4e0baSStefano Zampini   PetscFunctionReturn(0);
85128f4e0baSStefano Zampini }
8522e1947a5SStefano Zampini 
8532e1947a5SStefano Zampini #undef __FUNCT__
8542e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
855eb82efa4SStefano Zampini /*@
856a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
857a88811baSStefano Zampini 
858a88811baSStefano Zampini    Collective on MPI_Comm
859a88811baSStefano Zampini 
860a88811baSStefano Zampini    Input Parameters:
861a88811baSStefano Zampini +  B - the matrix
862a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
863a88811baSStefano Zampini            (same value is used for all local rows)
864a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
865a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
866a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
867a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
868a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
869a88811baSStefano Zampini            the diagonal entry even if it is zero.
870a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
871a88811baSStefano Zampini            submatrix (same value is used for all local rows).
872a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
873a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
874a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
875a88811baSStefano Zampini            structure. The size of this array is equal to the number
876a88811baSStefano Zampini            of local rows, i.e 'm'.
877a88811baSStefano Zampini 
878a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
879a88811baSStefano Zampini 
880a88811baSStefano Zampini    Level: intermediate
881a88811baSStefano Zampini 
882a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
883a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
884a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
885a88811baSStefano Zampini 
886a88811baSStefano Zampini .keywords: matrix
887a88811baSStefano Zampini 
8883c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
889a88811baSStefano Zampini @*/
8902e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
8912e1947a5SStefano Zampini {
8922e1947a5SStefano Zampini   PetscErrorCode ierr;
8932e1947a5SStefano Zampini 
8942e1947a5SStefano Zampini   PetscFunctionBegin;
8952e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
8962e1947a5SStefano Zampini   PetscValidType(B,1);
8972e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
8982e1947a5SStefano Zampini   PetscFunctionReturn(0);
8992e1947a5SStefano Zampini }
9002e1947a5SStefano Zampini 
9012e1947a5SStefano Zampini #undef __FUNCT__
9022e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
9037230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
9042e1947a5SStefano Zampini {
9052e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
90628f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
9072e1947a5SStefano Zampini   PetscErrorCode ierr;
9082e1947a5SStefano Zampini 
9092e1947a5SStefano Zampini   PetscFunctionBegin;
9106c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
911cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
9124f2d7cafSStefano Zampini 
9134f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
9144f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
9154f2d7cafSStefano Zampini 
9164f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
9174f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
9184f2d7cafSStefano Zampini 
91928f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
92028f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
92128f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
92228f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
9234f2d7cafSStefano Zampini 
9244f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
92528f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
9264f2d7cafSStefano Zampini 
9274f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
92828f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
9294f2d7cafSStefano Zampini 
9304f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
93128f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
9322e1947a5SStefano Zampini   PetscFunctionReturn(0);
9332e1947a5SStefano Zampini }
934b4319ba4SBarry Smith 
935b4319ba4SBarry Smith #undef __FUNCT__
9363927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
9373927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
9383927de2eSStefano Zampini {
9393927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
9403927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
941ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
9423927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
9433927de2eSStefano Zampini   PetscInt        lrows,lcols;
9443927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
9453927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
9463927de2eSStefano Zampini   PetscBool       isdense,issbaij;
9473927de2eSStefano Zampini   PetscErrorCode  ierr;
9483927de2eSStefano Zampini 
9493927de2eSStefano Zampini   PetscFunctionBegin;
9503927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
9513927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
9523927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
9533927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
9543927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
9553927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
956ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
957ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
9587230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
959ecf5a873SStefano Zampini   } else {
960ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
961ecf5a873SStefano Zampini   }
962ecf5a873SStefano Zampini 
9633927de2eSStefano Zampini   if (issbaij) {
9643927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
9653927de2eSStefano Zampini   }
9663927de2eSStefano Zampini   /*
967ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
9683927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
9693927de2eSStefano Zampini   */
970cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
9713927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
9723927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
9733927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
9743927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
9753927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
9763927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
9773927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
9783927de2eSStefano Zampini       row_ownership[j] = i;
9793927de2eSStefano Zampini     }
9803927de2eSStefano Zampini   }
9817230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
9823927de2eSStefano Zampini 
9833927de2eSStefano Zampini   /*
9843927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
9853927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
9863927de2eSStefano Zampini   */
9873927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
9883927de2eSStefano Zampini   /* preallocation as a MATAIJ */
9893927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
9903927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
991ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
9923927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
9933927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
994ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
9953927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
9963927de2eSStefano Zampini           my_dnz[i] += 1;
9973927de2eSStefano Zampini         } else { /* offdiag block */
9983927de2eSStefano Zampini           my_onz[i] += 1;
9993927de2eSStefano Zampini         }
10003927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
10013927de2eSStefano Zampini         if (i != j) {
10023927de2eSStefano Zampini           owner = row_ownership[index_col];
10033927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
10043927de2eSStefano Zampini             my_dnz[j] += 1;
10053927de2eSStefano Zampini           } else {
10063927de2eSStefano Zampini             my_onz[j] += 1;
10073927de2eSStefano Zampini           }
10083927de2eSStefano Zampini         }
10093927de2eSStefano Zampini       }
10103927de2eSStefano Zampini     }
1011bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1012bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1013bb1015c3SStefano Zampini     PetscBool      done;
1014bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1015bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1016bb1015c3SStefano Zampini     jptr = jj;
1017bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1018bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1019bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1020bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1021bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1022bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1023bb1015c3SStefano Zampini           my_dnz[i] += 1;
1024bb1015c3SStefano Zampini         } else { /* offdiag block */
1025bb1015c3SStefano Zampini           my_onz[i] += 1;
1026bb1015c3SStefano Zampini         }
1027bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1028bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1029bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1030bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1031bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1032bb1015c3SStefano Zampini           } else {
1033bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1034bb1015c3SStefano Zampini           }
1035bb1015c3SStefano Zampini         }
1036bb1015c3SStefano Zampini       }
1037bb1015c3SStefano Zampini     }
1038bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1039bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1040bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
10413927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
10423927de2eSStefano Zampini       const PetscInt *cols;
1043ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
10443927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
10453927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
10463927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1047ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
10483927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
10493927de2eSStefano Zampini           my_dnz[i] += 1;
10503927de2eSStefano Zampini         } else { /* offdiag block */
10513927de2eSStefano Zampini           my_onz[i] += 1;
10523927de2eSStefano Zampini         }
10533927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1054d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
10553927de2eSStefano Zampini           owner = row_ownership[index_col];
10563927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1057d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
10583927de2eSStefano Zampini           } else {
1059d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
10603927de2eSStefano Zampini           }
10613927de2eSStefano Zampini         }
10623927de2eSStefano Zampini       }
10633927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
10643927de2eSStefano Zampini     }
10653927de2eSStefano Zampini   }
1066ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1067ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
10687230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1069ecf5a873SStefano Zampini   }
10703927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1071ecf5a873SStefano Zampini 
1072ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
10733927de2eSStefano Zampini   if (maxreduce) {
10743927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
10753927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1076bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
10773927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
10783927de2eSStefano Zampini   } else {
10793927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
10803927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1081bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
10823927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
10833927de2eSStefano Zampini   }
10843927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
10853927de2eSStefano Zampini 
10863927de2eSStefano Zampini   /* Resize preallocation if overestimated */
10873927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
10883927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
10893927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
10903927de2eSStefano Zampini   }
10911670daf9Sstefano_zampini 
10921670daf9Sstefano_zampini   /* Set preallocation */
10933927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
10943927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
10953927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
10963927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
10973927de2eSStefano Zampini   }
10983927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
10993927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
11003927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
11013927de2eSStefano Zampini   if (issbaij) {
11023927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
11033927de2eSStefano Zampini   }
11043927de2eSStefano Zampini   PetscFunctionReturn(0);
11053927de2eSStefano Zampini }
11063927de2eSStefano Zampini 
11073927de2eSStefano Zampini #undef __FUNCT__
1108b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
11097230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1110b7ce53b6SStefano Zampini {
1111b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1112d9a9e74cSStefano Zampini   Mat            local_mat;
1113b7ce53b6SStefano Zampini   /* info on mat */
11143cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1115b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1116b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1117b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1118b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1119b9ed4604SStefano Zampini #endif
11207c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1121b7ce53b6SStefano Zampini   /* values insertion */
1122b7ce53b6SStefano Zampini   PetscScalar    *array;
1123b7ce53b6SStefano Zampini   /* work */
1124b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1125b7ce53b6SStefano Zampini 
1126b7ce53b6SStefano Zampini   PetscFunctionBegin;
1127b7ce53b6SStefano Zampini   /* get info from mat */
11287c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
11297c03b4e8SStefano Zampini   if (nsubdomains == 1) {
11301670daf9Sstefano_zampini     Mat            B;
11311670daf9Sstefano_zampini     IS             rows,cols;
11321670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
11331670daf9Sstefano_zampini 
11341670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
11351670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
11361670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
11371670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
11381670daf9Sstefano_zampini     ierr = MatConvert(matis->A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
11391670daf9Sstefano_zampini     ierr = MatGetSubMatrix(B,rows,cols,reuse,M);CHKERRQ(ierr);
11401670daf9Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
11411670daf9Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
11421670daf9Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
11431670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
11441670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
11457c03b4e8SStefano Zampini     PetscFunctionReturn(0);
11467c03b4e8SStefano Zampini   }
1147b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1148b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
11493cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1150b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1151b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
1152686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1153b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1154b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1155b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1156b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1157b9ed4604SStefano Zampini   lb[0] = isseqdense;
1158b9ed4604SStefano Zampini   lb[1] = isseqaij;
1159b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1160b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1161b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1162b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1163b9ed4604SStefano Zampini #endif
1164b7ce53b6SStefano Zampini 
1165b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
11663927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
11673cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
11683927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
1169b9ed4604SStefano Zampini     if (!isseqsbaij) {
1170b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1171b9ed4604SStefano Zampini     } else {
1172b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1173b9ed4604SStefano Zampini     }
11743927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1175b7ce53b6SStefano Zampini   } else {
11763cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1177b7ce53b6SStefano Zampini     /* some checks */
1178b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1179b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
11803cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
11816c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
11826c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
11836c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
11846c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
11856c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1186b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1187b7ce53b6SStefano Zampini   }
1188d9a9e74cSStefano Zampini 
1189b9ed4604SStefano Zampini   if (isseqsbaij) {
1190d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1191d9a9e74cSStefano Zampini   } else {
1192d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1193d9a9e74cSStefano Zampini     local_mat = matis->A;
1194d9a9e74cSStefano Zampini   }
1195686e3a49SStefano Zampini 
1196b7ce53b6SStefano Zampini   /* Set values */
1197ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1198b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
1199ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
1200ecf5a873SStefano Zampini 
1201ecf5a873SStefano Zampini     if (local_rows != local_cols) {
1202ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
1203ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1204ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
1205ecf5a873SStefano Zampini     } else {
1206ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
1207ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1208ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
1209ecf5a873SStefano Zampini     }
1210b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1211d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
1212ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
1213d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
1214ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
1215ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
1216ecf5a873SStefano Zampini     } else {
1217ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
1218ecf5a873SStefano Zampini     }
1219686e3a49SStefano Zampini   } else if (isseqaij) {
1220ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1221686e3a49SStefano Zampini     PetscBool done;
1222686e3a49SStefano Zampini 
1223d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1224bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1225d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1226686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1227ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1228686e3a49SStefano Zampini     }
1229d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1230bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1231d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1232686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1233ecf5a873SStefano Zampini     PetscInt i;
1234c0962df8SStefano Zampini 
1235686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1236686e3a49SStefano Zampini       PetscInt       j;
1237ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1238686e3a49SStefano Zampini 
1239ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1240ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1241ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1242686e3a49SStefano Zampini     }
1243b7ce53b6SStefano Zampini   }
1244b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1245d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1246b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1247b9ed4604SStefano Zampini   if (isseqdense) {
1248b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1249b7ce53b6SStefano Zampini   }
1250b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1251b7ce53b6SStefano Zampini }
1252b7ce53b6SStefano Zampini 
1253b7ce53b6SStefano Zampini #undef __FUNCT__
1254b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
1255b7ce53b6SStefano Zampini /*@
1256b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1257b7ce53b6SStefano Zampini 
1258b7ce53b6SStefano Zampini   Input Parameter:
1259b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1260b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1261b7ce53b6SStefano Zampini 
1262b7ce53b6SStefano Zampini   Output Parameter:
1263b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1264b7ce53b6SStefano Zampini 
1265b7ce53b6SStefano Zampini   Level: developer
1266b7ce53b6SStefano Zampini 
1267eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1268b7ce53b6SStefano Zampini 
1269b7ce53b6SStefano Zampini .seealso: MATIS
1270b7ce53b6SStefano Zampini @*/
1271b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1272b7ce53b6SStefano Zampini {
1273b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1274b7ce53b6SStefano Zampini 
1275b7ce53b6SStefano Zampini   PetscFunctionBegin;
1276b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1277b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1278b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1279b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1280b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1281b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
12826c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1283b7ce53b6SStefano Zampini   }
1284b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1285b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1286b7ce53b6SStefano Zampini }
1287b7ce53b6SStefano Zampini 
1288b7ce53b6SStefano Zampini #undef __FUNCT__
1289ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
1290ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1291ad6194a2SStefano Zampini {
1292ad6194a2SStefano Zampini   PetscErrorCode ierr;
1293ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1294ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1295ad6194a2SStefano Zampini   Mat            B,localmat;
1296ad6194a2SStefano Zampini 
1297ad6194a2SStefano Zampini   PetscFunctionBegin;
1298ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1299ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1300ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1301e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1302ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1303ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1304b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1305ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1306ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1307ad6194a2SStefano Zampini   *newmat = B;
1308ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1309ad6194a2SStefano Zampini }
1310ad6194a2SStefano Zampini 
1311ad6194a2SStefano Zampini #undef __FUNCT__
131269796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
1313a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
131469796d55SStefano Zampini {
131569796d55SStefano Zampini   PetscErrorCode ierr;
131669796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
131769796d55SStefano Zampini   PetscBool      local_sym;
131869796d55SStefano Zampini 
131969796d55SStefano Zampini   PetscFunctionBegin;
132069796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1321b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
132269796d55SStefano Zampini   PetscFunctionReturn(0);
132369796d55SStefano Zampini }
132469796d55SStefano Zampini 
132569796d55SStefano Zampini #undef __FUNCT__
132669796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
1327a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
132869796d55SStefano Zampini {
132969796d55SStefano Zampini   PetscErrorCode ierr;
133069796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
133169796d55SStefano Zampini   PetscBool      local_sym;
133269796d55SStefano Zampini 
133369796d55SStefano Zampini   PetscFunctionBegin;
133469796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1335b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
133669796d55SStefano Zampini   PetscFunctionReturn(0);
133769796d55SStefano Zampini }
133869796d55SStefano Zampini 
133969796d55SStefano Zampini #undef __FUNCT__
134045471136SStefano Zampini #define __FUNCT__ "MatIsStructurallySymmetric_IS"
134145471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
134245471136SStefano Zampini {
134345471136SStefano Zampini   PetscErrorCode ierr;
134445471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
134545471136SStefano Zampini   PetscBool      local_sym;
134645471136SStefano Zampini 
134745471136SStefano Zampini   PetscFunctionBegin;
134845471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
134945471136SStefano Zampini     *flg = PETSC_FALSE;
135045471136SStefano Zampini     PetscFunctionReturn(0);
135145471136SStefano Zampini   }
135245471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
135345471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
135445471136SStefano Zampini   PetscFunctionReturn(0);
135545471136SStefano Zampini }
135645471136SStefano Zampini 
135745471136SStefano Zampini #undef __FUNCT__
1358b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
1359a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1360b4319ba4SBarry Smith {
1361dfbe8321SBarry Smith   PetscErrorCode ierr;
1362b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1363b4319ba4SBarry Smith 
1364b4319ba4SBarry Smith   PetscFunctionBegin;
13656bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1366e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1367e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
13686bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
13696bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
13703fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1371a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1372a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1373a8116848SStefano Zampini   if (b->sf != b->csf) {
1374a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1375a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1376a8116848SStefano Zampini   }
137728f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
137828f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1379bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1380dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1381bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1382b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1383b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
13842e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1385cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1386b4319ba4SBarry Smith   PetscFunctionReturn(0);
1387b4319ba4SBarry Smith }
1388b4319ba4SBarry Smith 
1389b4319ba4SBarry Smith #undef __FUNCT__
1390b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
1391a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1392b4319ba4SBarry Smith {
1393dfbe8321SBarry Smith   PetscErrorCode ierr;
1394b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1395b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1396b4319ba4SBarry Smith 
1397b4319ba4SBarry Smith   PetscFunctionBegin;
1398b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1399e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1400e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1401b4319ba4SBarry Smith 
1402b4319ba4SBarry Smith   /* multiply the local matrix */
1403b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1404b4319ba4SBarry Smith 
1405b4319ba4SBarry Smith   /* scatter product back into global memory */
14062dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1407e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1408e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1409b4319ba4SBarry Smith   PetscFunctionReturn(0);
1410b4319ba4SBarry Smith }
1411b4319ba4SBarry Smith 
1412b4319ba4SBarry Smith #undef __FUNCT__
14132e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
1414a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
14152e74eeadSLisandro Dalcin {
1416650997f4SStefano Zampini   Vec            temp_vec;
14172e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14182e74eeadSLisandro Dalcin 
14192e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1420650997f4SStefano Zampini   if (v3 != v2) {
1421650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1422650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1423650997f4SStefano Zampini   } else {
1424650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1425650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1426650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1427650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1428650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1429650997f4SStefano Zampini   }
14302e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14312e74eeadSLisandro Dalcin }
14322e74eeadSLisandro Dalcin 
14332e74eeadSLisandro Dalcin #undef __FUNCT__
14342e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
1435a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
14362e74eeadSLisandro Dalcin {
14372e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
14382e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14392e74eeadSLisandro Dalcin 
1440e176bc59SStefano Zampini   PetscFunctionBegin;
14412e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1442e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1443e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14442e74eeadSLisandro Dalcin 
14452e74eeadSLisandro Dalcin   /* multiply the local matrix */
1446e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
14472e74eeadSLisandro Dalcin 
14482e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1449e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1450e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1451e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14522e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14532e74eeadSLisandro Dalcin }
14542e74eeadSLisandro Dalcin 
14552e74eeadSLisandro Dalcin #undef __FUNCT__
14562e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
1457a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
14582e74eeadSLisandro Dalcin {
1459650997f4SStefano Zampini   Vec            temp_vec;
14602e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14612e74eeadSLisandro Dalcin 
14622e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1463650997f4SStefano Zampini   if (v3 != v2) {
1464650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1465650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1466650997f4SStefano Zampini   } else {
1467650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1468650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1469650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1470650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1471650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1472650997f4SStefano Zampini   }
14732e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14742e74eeadSLisandro Dalcin }
14752e74eeadSLisandro Dalcin 
14762e74eeadSLisandro Dalcin #undef __FUNCT__
1477b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
1478a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1479b4319ba4SBarry Smith {
1480b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1481dfbe8321SBarry Smith   PetscErrorCode ierr;
1482b4319ba4SBarry Smith   PetscViewer    sviewer;
1483ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1484b4319ba4SBarry Smith 
1485b4319ba4SBarry Smith   PetscFunctionBegin;
1486ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1487ee2491ecSStefano Zampini   if (isascii)  {
1488ee2491ecSStefano Zampini     PetscViewerFormat format;
1489ee2491ecSStefano Zampini 
1490ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1491ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1492ee2491ecSStefano Zampini   }
1493ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
14943f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1495b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
14963f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
14976e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1498b4319ba4SBarry Smith   PetscFunctionReturn(0);
1499b4319ba4SBarry Smith }
1500b4319ba4SBarry Smith 
1501b4319ba4SBarry Smith #undef __FUNCT__
1502b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
1503a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1504b4319ba4SBarry Smith {
1505dfbe8321SBarry Smith   PetscErrorCode ierr;
1506e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1507b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1508b4319ba4SBarry Smith   IS             from,to;
1509e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1510b4319ba4SBarry Smith 
1511b4319ba4SBarry Smith   PetscFunctionBegin;
1512784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1513e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
15143bbff08aSStefano Zampini   /* Destroy any previous data */
151570cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
151670cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
15173fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1518e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1519e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
15201c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
152128f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
152228f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
15233bbff08aSStefano Zampini 
15243bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1525fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1526fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1527fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1528fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1529b4319ba4SBarry Smith 
1530b4319ba4SBarry Smith   /* Create the local matrix A */
1531e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1532e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1533e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1534e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1535f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1536e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1537e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1538e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1539ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1540ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1541b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1542b4319ba4SBarry Smith 
1543f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1544b4319ba4SBarry Smith     /* Create the local work vectors */
15453bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1546b4319ba4SBarry Smith 
1547e176bc59SStefano Zampini     /* setup the global to local scatters */
1548e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1549e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1550784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1551e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1552e176bc59SStefano Zampini     if (rmapping != cmapping) {
1553e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1554e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1555e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1556e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1557e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1558e176bc59SStefano Zampini     } else {
1559e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1560e176bc59SStefano Zampini       is->cctx = is->rctx;
1561e176bc59SStefano Zampini     }
15623fd1c9e7SStefano Zampini 
15633fd1c9e7SStefano Zampini     /* interface counter vector (local) */
15643fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
15653fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
15663fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15673fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15683fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15693fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15703fd1c9e7SStefano Zampini 
15713fd1c9e7SStefano Zampini     /* free workspace */
1572e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1573e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
15746bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
15756bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1576f26d0771SStefano Zampini   }
15779c0b00dbSStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1578b4319ba4SBarry Smith   PetscFunctionReturn(0);
1579b4319ba4SBarry Smith }
1580b4319ba4SBarry Smith 
15812e74eeadSLisandro Dalcin #undef __FUNCT__
15822e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
1583a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
15842e74eeadSLisandro Dalcin {
15852e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
15862e74eeadSLisandro Dalcin   PetscErrorCode ierr;
158797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
158897563a80SStefano Zampini   PetscInt       i,zm,zn;
158997563a80SStefano Zampini #endif
1590f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
15912e74eeadSLisandro Dalcin 
15922e74eeadSLisandro Dalcin   PetscFunctionBegin;
15932e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1594f26d0771SStefano 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);
159597563a80SStefano Zampini   /* count negative indices */
159697563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
159797563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
15982e74eeadSLisandro Dalcin #endif
159997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
160097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
160197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
160297563a80SStefano Zampini   /* count negative indices (should be the same as before) */
160397563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
160497563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
160597563a80SStefano 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");
160697563a80SStefano 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");
160797563a80SStefano Zampini #endif
16082e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
16092e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
16102e74eeadSLisandro Dalcin }
16112e74eeadSLisandro Dalcin 
1612b4319ba4SBarry Smith #undef __FUNCT__
161397563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS"
1614a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
161597563a80SStefano Zampini {
161697563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
161797563a80SStefano Zampini   PetscErrorCode ierr;
161897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
161997563a80SStefano Zampini   PetscInt       i,zm,zn;
162097563a80SStefano Zampini #endif
1621f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
162297563a80SStefano Zampini 
162397563a80SStefano Zampini   PetscFunctionBegin;
162497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1625f26d0771SStefano 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);
162697563a80SStefano Zampini   /* count negative indices */
162797563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
162897563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
162997563a80SStefano Zampini #endif
163097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
163197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
163297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
163397563a80SStefano Zampini   /* count negative indices (should be the same as before) */
163497563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
163597563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
163697563a80SStefano 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");
163797563a80SStefano 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");
163897563a80SStefano Zampini #endif
163997563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
164097563a80SStefano Zampini   PetscFunctionReturn(0);
164197563a80SStefano Zampini }
164297563a80SStefano Zampini 
164397563a80SStefano Zampini #undef __FUNCT__
1644b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
1645a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1646b4319ba4SBarry Smith {
1647dfbe8321SBarry Smith   PetscErrorCode ierr;
1648b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1649b4319ba4SBarry Smith 
1650b4319ba4SBarry Smith   PetscFunctionBegin;
1651b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1652b4319ba4SBarry Smith   PetscFunctionReturn(0);
1653b4319ba4SBarry Smith }
1654b4319ba4SBarry Smith 
1655b4319ba4SBarry Smith #undef __FUNCT__
1656f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
1657a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1658f0006bf2SLisandro Dalcin {
1659f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1660f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1661f0006bf2SLisandro Dalcin 
1662f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1663f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1664f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1665f0006bf2SLisandro Dalcin }
1666f0006bf2SLisandro Dalcin 
1667f0006bf2SLisandro Dalcin #undef __FUNCT__
1668f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private"
1669f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
16702e74eeadSLisandro Dalcin {
1671f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
16722e74eeadSLisandro Dalcin   PetscErrorCode ierr;
16732e74eeadSLisandro Dalcin 
16742e74eeadSLisandro Dalcin   PetscFunctionBegin;
1675f0ae7da4SStefano Zampini   if (!n) {
1676f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1677f0ae7da4SStefano Zampini   } else {
1678f0ae7da4SStefano Zampini     PetscInt i;
1679f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1680f0ae7da4SStefano Zampini 
1681f0ae7da4SStefano Zampini     if (columns) {
1682f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1683f0ae7da4SStefano Zampini     } else {
1684f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
16852e74eeadSLisandro Dalcin     }
1686f0ae7da4SStefano Zampini     if (diag != 0.) {
1687f0ae7da4SStefano Zampini       const PetscScalar *array;
1688f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1689f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1690f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1691f0ae7da4SStefano Zampini       }
1692f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1693f0ae7da4SStefano Zampini     }
1694f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1695f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1696f0ae7da4SStefano Zampini   }
16972e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
16982e74eeadSLisandro Dalcin }
16992e74eeadSLisandro Dalcin 
17002e74eeadSLisandro Dalcin #undef __FUNCT__
1701f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS"
1702f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
1703b4319ba4SBarry Smith {
17046e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
17056e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
17066e520ac8SStefano Zampini   PetscInt       *lrows;
1707dfbe8321SBarry Smith   PetscErrorCode ierr;
1708b4319ba4SBarry Smith 
1709b4319ba4SBarry Smith   PetscFunctionBegin;
1710f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1711f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1712f0ae7da4SStefano Zampini     PetscBool cong;
1713f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1714f0ae7da4SStefano 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");
1715f0ae7da4SStefano 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");
1716f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1717b4319ba4SBarry Smith   }
1718f0ae7da4SStefano Zampini #endif
17196e520ac8SStefano Zampini   /* get locally owned rows */
1720f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
17216e520ac8SStefano Zampini   /* fix right hand side if needed */
17226e520ac8SStefano Zampini   if (x && b) {
17236e520ac8SStefano Zampini     const PetscScalar *xx;
17246e520ac8SStefano Zampini     PetscScalar       *bb;
17252205254eSKarl Rupp 
17266e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
17276e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
17286e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
17296e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
17306e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
1731b4319ba4SBarry Smith   }
17326e520ac8SStefano Zampini   /* get rows associated to the local matrices */
17333d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
17346e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
17356e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
17366e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
17376e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
17386e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
17396e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17406e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17416e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
17426e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1743f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
17446e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
1745b4319ba4SBarry Smith   PetscFunctionReturn(0);
1746b4319ba4SBarry Smith }
1747b4319ba4SBarry Smith 
1748b4319ba4SBarry Smith #undef __FUNCT__
1749f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS"
1750f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1751b4319ba4SBarry Smith {
1752b4319ba4SBarry Smith   PetscErrorCode ierr;
1753b4319ba4SBarry Smith 
1754b4319ba4SBarry Smith   PetscFunctionBegin;
1755f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1756f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1757f0ae7da4SStefano Zampini }
1758b4319ba4SBarry Smith 
1759f0ae7da4SStefano Zampini #undef __FUNCT__
1760f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS"
1761f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1762f0ae7da4SStefano Zampini {
1763f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1764f0ae7da4SStefano Zampini 
1765f0ae7da4SStefano Zampini   PetscFunctionBegin;
1766f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1767b4319ba4SBarry Smith   PetscFunctionReturn(0);
1768b4319ba4SBarry Smith }
1769b4319ba4SBarry Smith 
1770b4319ba4SBarry Smith #undef __FUNCT__
1771b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
1772a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1773b4319ba4SBarry Smith {
1774b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1775dfbe8321SBarry Smith   PetscErrorCode ierr;
1776b4319ba4SBarry Smith 
1777b4319ba4SBarry Smith   PetscFunctionBegin;
1778b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1779b4319ba4SBarry Smith   PetscFunctionReturn(0);
1780b4319ba4SBarry Smith }
1781b4319ba4SBarry Smith 
1782b4319ba4SBarry Smith #undef __FUNCT__
1783b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
1784a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1785b4319ba4SBarry Smith {
1786b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1787dfbe8321SBarry Smith   PetscErrorCode ierr;
1788b4319ba4SBarry Smith 
1789b4319ba4SBarry Smith   PetscFunctionBegin;
1790b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1791b4319ba4SBarry Smith   PetscFunctionReturn(0);
1792b4319ba4SBarry Smith }
1793b4319ba4SBarry Smith 
1794b4319ba4SBarry Smith #undef __FUNCT__
1795b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
1796a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1797b4319ba4SBarry Smith {
1798b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1799b4319ba4SBarry Smith 
1800b4319ba4SBarry Smith   PetscFunctionBegin;
1801b4319ba4SBarry Smith   *local = is->A;
1802b4319ba4SBarry Smith   PetscFunctionReturn(0);
1803b4319ba4SBarry Smith }
1804b4319ba4SBarry Smith 
1805b4319ba4SBarry Smith #undef __FUNCT__
1806b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
1807b4319ba4SBarry Smith /*@
1808b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1809b4319ba4SBarry Smith 
1810b4319ba4SBarry Smith   Input Parameter:
1811b4319ba4SBarry Smith .  mat - the matrix
1812b4319ba4SBarry Smith 
1813b4319ba4SBarry Smith   Output Parameter:
1814eb82efa4SStefano Zampini .  local - the local matrix
1815b4319ba4SBarry Smith 
1816b4319ba4SBarry Smith   Level: advanced
1817b4319ba4SBarry Smith 
1818b4319ba4SBarry Smith   Notes:
1819b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1820b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1821b4319ba4SBarry Smith   of the MatSetValues() operation.
1822b4319ba4SBarry Smith 
1823b4319ba4SBarry Smith .seealso: MATIS
1824b4319ba4SBarry Smith @*/
18257087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1826b4319ba4SBarry Smith {
18274ac538c5SBarry Smith   PetscErrorCode ierr;
1828b4319ba4SBarry Smith 
1829b4319ba4SBarry Smith   PetscFunctionBegin;
18300700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1831b4319ba4SBarry Smith   PetscValidPointer(local,2);
18324ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1833b4319ba4SBarry Smith   PetscFunctionReturn(0);
1834b4319ba4SBarry Smith }
1835b4319ba4SBarry Smith 
18363b03a366Sstefano_zampini #undef __FUNCT__
18373b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
1838a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
18393b03a366Sstefano_zampini {
18403b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
18413b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
18423b03a366Sstefano_zampini   PetscErrorCode ierr;
18433b03a366Sstefano_zampini 
18443b03a366Sstefano_zampini   PetscFunctionBegin;
18454e4c7dbeSStefano Zampini   if (is->A) {
18463b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
18473b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1848f0ae7da4SStefano 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);
18494e4c7dbeSStefano Zampini   }
18503b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
18513b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
18523b03a366Sstefano_zampini   is->A = local;
18533b03a366Sstefano_zampini   PetscFunctionReturn(0);
18543b03a366Sstefano_zampini }
18553b03a366Sstefano_zampini 
18563b03a366Sstefano_zampini #undef __FUNCT__
18573b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
18583b03a366Sstefano_zampini /*@
1859eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
18603b03a366Sstefano_zampini 
18613b03a366Sstefano_zampini   Input Parameter:
18623b03a366Sstefano_zampini .  mat - the matrix
1863eb82efa4SStefano Zampini .  local - the local matrix
18643b03a366Sstefano_zampini 
18653b03a366Sstefano_zampini   Output Parameter:
18663b03a366Sstefano_zampini 
18673b03a366Sstefano_zampini   Level: advanced
18683b03a366Sstefano_zampini 
18693b03a366Sstefano_zampini   Notes:
18703b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
18713b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
18723b03a366Sstefano_zampini 
18733b03a366Sstefano_zampini .seealso: MATIS
18743b03a366Sstefano_zampini @*/
18753b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
18763b03a366Sstefano_zampini {
18773b03a366Sstefano_zampini   PetscErrorCode ierr;
18783b03a366Sstefano_zampini 
18793b03a366Sstefano_zampini   PetscFunctionBegin;
18803b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1881b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
18823b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
18833b03a366Sstefano_zampini   PetscFunctionReturn(0);
18843b03a366Sstefano_zampini }
18853b03a366Sstefano_zampini 
18866726f965SBarry Smith #undef __FUNCT__
18876726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
1888a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
18896726f965SBarry Smith {
18906726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
18916726f965SBarry Smith   PetscErrorCode ierr;
18926726f965SBarry Smith 
18936726f965SBarry Smith   PetscFunctionBegin;
18946726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
18956726f965SBarry Smith   PetscFunctionReturn(0);
18966726f965SBarry Smith }
18976726f965SBarry Smith 
18986726f965SBarry Smith #undef __FUNCT__
18992e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
1900a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
19012e74eeadSLisandro Dalcin {
19022e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
19032e74eeadSLisandro Dalcin   PetscErrorCode ierr;
19042e74eeadSLisandro Dalcin 
19052e74eeadSLisandro Dalcin   PetscFunctionBegin;
19062e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
19072e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
19082e74eeadSLisandro Dalcin }
19092e74eeadSLisandro Dalcin 
19102e74eeadSLisandro Dalcin #undef __FUNCT__
19112e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
1912a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
19132e74eeadSLisandro Dalcin {
19142e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
19152e74eeadSLisandro Dalcin   PetscErrorCode ierr;
19162e74eeadSLisandro Dalcin 
19172e74eeadSLisandro Dalcin   PetscFunctionBegin;
19182e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
1919e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
19202e74eeadSLisandro Dalcin 
19212e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
19222e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
1923e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1924e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19252e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
19262e74eeadSLisandro Dalcin }
19272e74eeadSLisandro Dalcin 
19282e74eeadSLisandro Dalcin #undef __FUNCT__
19296726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
1930a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
19316726f965SBarry Smith {
19326726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
19336726f965SBarry Smith   PetscErrorCode ierr;
19346726f965SBarry Smith 
19356726f965SBarry Smith   PetscFunctionBegin;
19364e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
19376726f965SBarry Smith   PetscFunctionReturn(0);
19386726f965SBarry Smith }
19396726f965SBarry Smith 
1940284134d9SBarry Smith #undef __FUNCT__
1941f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS"
1942f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
1943f26d0771SStefano Zampini {
1944f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
1945f26d0771SStefano Zampini   Mat_IS         *x;
1946f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1947f26d0771SStefano Zampini   PetscBool      ismatis;
1948f26d0771SStefano Zampini #endif
1949f26d0771SStefano Zampini   PetscErrorCode ierr;
1950f26d0771SStefano Zampini 
1951f26d0771SStefano Zampini   PetscFunctionBegin;
1952f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1953f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
1954f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
1955f26d0771SStefano Zampini #endif
1956f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
1957f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
1958f26d0771SStefano Zampini   PetscFunctionReturn(0);
1959f26d0771SStefano Zampini }
1960f26d0771SStefano Zampini 
1961f26d0771SStefano Zampini #undef __FUNCT__
1962f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS"
1963f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
1964f26d0771SStefano Zampini {
1965f26d0771SStefano Zampini   Mat                    lA;
1966f26d0771SStefano Zampini   Mat_IS                 *matis;
1967f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
1968f26d0771SStefano Zampini   IS                     is;
1969f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
1970f26d0771SStefano Zampini   PetscInt               nrg;
1971f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
1972f26d0771SStefano Zampini   PetscErrorCode         ierr;
1973f26d0771SStefano Zampini 
1974f26d0771SStefano Zampini   PetscFunctionBegin;
1975f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1976f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
1977f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
1978f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
1979f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1980f0ae7da4SStefano 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);
1981f26d0771SStefano Zampini #endif
1982f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
1983f26d0771SStefano Zampini   /* map from [0,nrl) to row */
1984f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
1985f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1986f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
1987f26d0771SStefano Zampini #else
1988f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
1989f26d0771SStefano Zampini #endif
1990f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
1991f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1992f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1993f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1994f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
1995f26d0771SStefano Zampini   /* compute new l2g map for columns */
1996f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
1997f26d0771SStefano Zampini     const PetscInt *cg,*cl;
1998f26d0771SStefano Zampini     PetscInt       ncg;
1999f26d0771SStefano Zampini     PetscInt       ncl;
2000f26d0771SStefano Zampini 
2001f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2002f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2003f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2004f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2005f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2006f0ae7da4SStefano 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);
2007f26d0771SStefano Zampini #endif
2008f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2009f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2010f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2011f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2012f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2013f26d0771SStefano Zampini #else
2014f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2015f26d0771SStefano Zampini #endif
2016f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2017f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2018f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2019f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2020f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2021f26d0771SStefano Zampini   } else {
2022f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2023f26d0771SStefano Zampini     cl2g = rl2g;
2024f26d0771SStefano Zampini   }
2025f26d0771SStefano Zampini   /* create the MATIS submatrix */
2026f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2027f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2028f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2029f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2030b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2031f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2032f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2033f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2034f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2035f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2036f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2037f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2038f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2039f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2040f26d0771SStefano Zampini   /* remove unsupported ops */
2041f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2042f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2043f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2044f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2045f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2046f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2047f26d0771SStefano Zampini   PetscFunctionReturn(0);
2048f26d0771SStefano Zampini }
2049f26d0771SStefano Zampini 
2050f26d0771SStefano Zampini #undef __FUNCT__
2051284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
2052284134d9SBarry Smith /*@
20533c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2054284134d9SBarry Smith        process but not across processes.
2055284134d9SBarry Smith 
2056284134d9SBarry Smith    Input Parameters:
2057284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2058e176bc59SStefano Zampini .     bs      - block size of the matrix
2059df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2060e176bc59SStefano Zampini .     rmap    - local to global map for rows
2061e176bc59SStefano Zampini -     cmap    - local to global map for cols
2062284134d9SBarry Smith 
2063284134d9SBarry Smith    Output Parameter:
2064284134d9SBarry Smith .    A - the resulting matrix
2065284134d9SBarry Smith 
20668e6c10adSSatish Balay    Level: advanced
20678e6c10adSSatish Balay 
20683c212e90SHong Zhang    Notes: See MATIS for more details.
20696fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
20706fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
20713c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2072284134d9SBarry Smith 
2073284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2074284134d9SBarry Smith @*/
2075e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2076284134d9SBarry Smith {
2077284134d9SBarry Smith   PetscErrorCode ierr;
2078284134d9SBarry Smith 
2079284134d9SBarry Smith   PetscFunctionBegin;
20806fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2081284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
20826fdf41d1SStefano Zampini   if (bs > 0) {
2083d3ee2243SStefano Zampini     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
20846fdf41d1SStefano Zampini   }
2085284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
2086284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2087e176bc59SStefano Zampini   if (rmap && cmap) {
2088e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2089e176bc59SStefano Zampini   } else if (!rmap) {
2090e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2091e176bc59SStefano Zampini   } else {
2092e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2093e176bc59SStefano Zampini   }
2094284134d9SBarry Smith   PetscFunctionReturn(0);
2095284134d9SBarry Smith }
2096284134d9SBarry Smith 
2097b4319ba4SBarry Smith /*MC
2098f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2099b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2100b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2101b4319ba4SBarry Smith    product is handled "implicitly".
2102b4319ba4SBarry Smith 
2103b4319ba4SBarry Smith    Operations Provided:
21046726f965SBarry Smith +  MatMult()
21052e74eeadSLisandro Dalcin .  MatMultAdd()
21062e74eeadSLisandro Dalcin .  MatMultTranspose()
21072e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
21086726f965SBarry Smith .  MatZeroEntries()
21096726f965SBarry Smith .  MatSetOption()
21102e74eeadSLisandro Dalcin .  MatZeroRows()
21112e74eeadSLisandro Dalcin .  MatSetValues()
211297563a80SStefano Zampini .  MatSetValuesBlocked()
21136726f965SBarry Smith .  MatSetValuesLocal()
211497563a80SStefano Zampini .  MatSetValuesBlockedLocal()
21152e74eeadSLisandro Dalcin .  MatScale()
21162e74eeadSLisandro Dalcin .  MatGetDiagonal()
21172b404112SStefano Zampini .  MatMissingDiagonal()
21182b404112SStefano Zampini .  MatDuplicate()
21192b404112SStefano Zampini .  MatCopy()
2120f26d0771SStefano Zampini .  MatAXPY()
2121f26d0771SStefano Zampini .  MatGetSubMatrix()
2122f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2123d7f69cd0SStefano Zampini .  MatTranspose()
21246726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2125b4319ba4SBarry Smith 
2126b4319ba4SBarry Smith    Options Database Keys:
2127b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2128b4319ba4SBarry Smith 
2129b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
2130b4319ba4SBarry Smith 
2131b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2132b4319ba4SBarry Smith 
2133b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2134eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2135b4319ba4SBarry Smith 
2136b4319ba4SBarry Smith   Level: advanced
2137b4319ba4SBarry Smith 
2138f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2139b4319ba4SBarry Smith 
2140b4319ba4SBarry Smith M*/
2141b4319ba4SBarry Smith 
2142b4319ba4SBarry Smith #undef __FUNCT__
2143b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
21448cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2145b4319ba4SBarry Smith {
2146dfbe8321SBarry Smith   PetscErrorCode ierr;
2147b4319ba4SBarry Smith   Mat_IS         *b;
2148b4319ba4SBarry Smith 
2149b4319ba4SBarry Smith   PetscFunctionBegin;
2150b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2151b4319ba4SBarry Smith   A->data = (void*)b;
2152b4319ba4SBarry Smith 
2153e176bc59SStefano Zampini   /* matrix ops */
2154e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2155b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
21562e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
21572e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
21582e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2159b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2160b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
21612e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
216298921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2163b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2164f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
21652e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2166f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2167b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2168b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2169b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
21706726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
21712e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
21722e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
21736726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
217469796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
217569796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
217645471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2177ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
21786bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
21792b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2180659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
2181a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
2182f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
21833fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
21843fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2185d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
2186b4319ba4SBarry Smith 
2187b7ce53b6SStefano Zampini   /* special MATIS functions */
2188bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
2189bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2190b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
21912e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2192cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
219317667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2194b4319ba4SBarry Smith   PetscFunctionReturn(0);
2195b4319ba4SBarry Smith }
2196