xref: /petsc/src/mat/impls/is/matis.c (revision cf37664f2dbf3effe674ec5ac2718028c1621ae0)
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__
175b003df0Sstefano_zampini #define __FUNCT__ "MatISContainerDestroyFields_Private"
185b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
195b003df0Sstefano_zampini {
205b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
215b003df0Sstefano_zampini   PetscInt         i;
225b003df0Sstefano_zampini   PetscErrorCode   ierr;
235b003df0Sstefano_zampini 
245b003df0Sstefano_zampini   PetscFunctionBeginUser;
255b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
265b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
275b003df0Sstefano_zampini   }
285b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
295b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
305b003df0Sstefano_zampini   }
315b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
325b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
335b003df0Sstefano_zampini   PetscFunctionReturn(0);
345b003df0Sstefano_zampini }
35a72627d2SStefano Zampini 
3628f4e0baSStefano Zampini #undef __FUNCT__
375b003df0Sstefano_zampini #define __FUNCT__ "MatISContainerDestroyArray_Private"
385b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyArray_Private(void *ptr)
397fa8f2d3SStefano 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);
1355b003df0Sstefano_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 {
1687fa8f2d3SStefano Zampini   PetscErrorCode ierr;
1697fa8f2d3SStefano Zampini 
1707fa8f2d3SStefano 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);
1747fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
1757fa8f2d3SStefano Zampini }
1767fa8f2d3SStefano Zampini 
1777fa8f2d3SStefano 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;
1855b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
1865b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
1879e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
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);
2085b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
2099e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
2105e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
2119e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);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;
2169e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,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 */
2229e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
2239e7b2b25Sstefano_zampini       if (istrans[ij]) {
2249e7b2b25Sstefano_zampini         Mat T,lT;
2259e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2269e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
2279e7b2b25Sstefano_zampini         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) (transposed) is not of type MATIS",i,j);
2289e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
2299e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
2309e7b2b25Sstefano_zampini       } else {
2315e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
2325e3038f0Sstefano_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);
2339e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
2349e7b2b25Sstefano_zampini       }
2355e3038f0Sstefano_zampini 
2365e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
2375e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
2389e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
2395e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
2405e3038f0Sstefano_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);
2415e3038f0Sstefano_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);
2425e3038f0Sstefano_zampini       lr[i] = l1;
2435e3038f0Sstefano_zampini       lc[j] = l2;
2445e3038f0Sstefano_zampini 
2455e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
2465e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
2475e3038f0Sstefano_zampini     }
2485e3038f0Sstefano_zampini   }
2495e3038f0Sstefano_zampini 
2505e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
2515e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
2525e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2535e3038f0Sstefano_zampini     rl2g = NULL;
2545e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2555e3038f0Sstefano_zampini       PetscInt n1,n2;
2565e3038f0Sstefano_zampini 
2575e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2589e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
2599e7b2b25Sstefano_zampini         Mat T;
2609e7b2b25Sstefano_zampini 
2619e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
2629e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
2639e7b2b25Sstefano_zampini       } else {
2645e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
2659e7b2b25Sstefano_zampini       }
2665e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2675e3038f0Sstefano_zampini       if (!n1) continue;
2685e3038f0Sstefano_zampini       if (!rl2g) {
2695e3038f0Sstefano_zampini         rl2g = cl2g;
2705e3038f0Sstefano_zampini       } else {
2715e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2725e3038f0Sstefano_zampini         PetscBool      same;
2735e3038f0Sstefano_zampini 
2745e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2755e3038f0Sstefano_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);
2765e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2775e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2785e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2795e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2805e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2815e3038f0Sstefano_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);
2825e3038f0Sstefano_zampini       }
2835e3038f0Sstefano_zampini     }
2845e3038f0Sstefano_zampini   }
2855e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
2865e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
2875e3038f0Sstefano_zampini     rl2g = NULL;
2885e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
2895e3038f0Sstefano_zampini       PetscInt n1,n2;
2905e3038f0Sstefano_zampini 
2915e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
2929e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
2939e7b2b25Sstefano_zampini         Mat T;
2949e7b2b25Sstefano_zampini 
2959e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
2969e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
2979e7b2b25Sstefano_zampini       } else {
2985e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
2999e7b2b25Sstefano_zampini       }
3005e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
3015e3038f0Sstefano_zampini       if (!n1) continue;
3025e3038f0Sstefano_zampini       if (!rl2g) {
3035e3038f0Sstefano_zampini         rl2g = cl2g;
3045e3038f0Sstefano_zampini       } else {
3055e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
3065e3038f0Sstefano_zampini         PetscBool      same;
3075e3038f0Sstefano_zampini 
3085e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
3095e3038f0Sstefano_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);
3105e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
3115e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
3125e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
3135e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
3145e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
3155e3038f0Sstefano_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);
3165e3038f0Sstefano_zampini       }
3175e3038f0Sstefano_zampini     }
3185e3038f0Sstefano_zampini   }
3195e3038f0Sstefano_zampini #endif
3205e3038f0Sstefano_zampini 
3215e3038f0Sstefano_zampini   B = NULL;
3225e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
3235b003df0Sstefano_zampini     PetscInt stl;
3245b003df0Sstefano_zampini 
3255e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
3265e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
3275e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3285b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
3295e3038f0Sstefano_zampini       Mat            usedmat;
3305e3038f0Sstefano_zampini       Mat_IS         *matis;
3315e3038f0Sstefano_zampini       const PetscInt *idxs;
3325e3038f0Sstefano_zampini 
3335e3038f0Sstefano_zampini       /* local IS for local NEST */
3345b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
3355e3038f0Sstefano_zampini 
3365e3038f0Sstefano_zampini       /* l2gmap */
3375e3038f0Sstefano_zampini       j = 0;
3385e3038f0Sstefano_zampini       usedmat = nest[i][j];
3399e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
3409e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
3419e7b2b25Sstefano_zampini 
3429e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3439e7b2b25Sstefano_zampini         Mat T;
3449e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3459e7b2b25Sstefano_zampini         usedmat = T;
3469e7b2b25Sstefano_zampini       }
34782d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3485e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3495e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
3509e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
3519e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3529e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3539e7b2b25Sstefano_zampini       } else {
3545e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3555e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3569e7b2b25Sstefano_zampini       }
3575e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
3585e3038f0Sstefano_zampini       stl += lr[i];
3595e3038f0Sstefano_zampini     }
3605e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
3615e3038f0Sstefano_zampini 
3625e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
3635e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
3645e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3655b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
3665e3038f0Sstefano_zampini       Mat            usedmat;
3675e3038f0Sstefano_zampini       Mat_IS         *matis;
3685e3038f0Sstefano_zampini       const PetscInt *idxs;
3695e3038f0Sstefano_zampini 
3705e3038f0Sstefano_zampini       /* local IS for local NEST */
3715b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
3725e3038f0Sstefano_zampini 
3735e3038f0Sstefano_zampini       /* l2gmap */
3745e3038f0Sstefano_zampini       j = 0;
3755e3038f0Sstefano_zampini       usedmat = nest[j][i];
3769e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
3779e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
3789e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3799e7b2b25Sstefano_zampini         Mat T;
3809e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
3819e7b2b25Sstefano_zampini         usedmat = T;
3829e7b2b25Sstefano_zampini       }
38382d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3845e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3855e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
3869e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
3879e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3889e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3899e7b2b25Sstefano_zampini       } else {
3905e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3915e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3929e7b2b25Sstefano_zampini       }
3935e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
3945e3038f0Sstefano_zampini       stl += lc[i];
3955e3038f0Sstefano_zampini     }
3965e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
3975e3038f0Sstefano_zampini 
3985e3038f0Sstefano_zampini     /* Create MATIS */
3995e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
4005e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
4015e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
4025e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
4035e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
4045e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
4055e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
4065e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
4075e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
4089e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
4099e7b2b25Sstefano_zampini       if (istrans[i]) {
4109e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
4119e7b2b25Sstefano_zampini       }
4129e7b2b25Sstefano_zampini     }
4135e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
4145e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
4155e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4165e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4175e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
4185e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
4195e3038f0Sstefano_zampini     } else {
4205e3038f0Sstefano_zampini       *newmat = B;
4215e3038f0Sstefano_zampini     }
4225e3038f0Sstefano_zampini   } else {
4235e3038f0Sstefano_zampini     if (lreuse) {
4245e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4255e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
4265e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
4275e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
4285e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
4299e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
4309e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
4319e7b2b25Sstefano_zampini             }
4325e3038f0Sstefano_zampini           }
4335e3038f0Sstefano_zampini         }
4345e3038f0Sstefano_zampini       }
4355e3038f0Sstefano_zampini     } else {
4365b003df0Sstefano_zampini       PetscInt stl;
4375b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
4385b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
4395b003df0Sstefano_zampini         stl  += lr[i];
4405e3038f0Sstefano_zampini       }
4415b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
4425b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
4435b003df0Sstefano_zampini         stl  += lc[i];
4445e3038f0Sstefano_zampini       }
4455e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
4469e7b2b25Sstefano_zampini       if (istrans[i]) {
4479e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
4489e7b2b25Sstefano_zampini       }
4495e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
4505e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
4515e3038f0Sstefano_zampini     }
4525e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4535e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4545e3038f0Sstefano_zampini   }
4555e3038f0Sstefano_zampini 
4565b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
4575b003df0Sstefano_zampini   convert = PETSC_FALSE;
4585b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
4595b003df0Sstefano_zampini   if (convert) {
4605b003df0Sstefano_zampini     Mat              M;
4615b003df0Sstefano_zampini     MatISLocalFields lf;
4625b003df0Sstefano_zampini     PetscContainer   c;
4635b003df0Sstefano_zampini 
4645b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4655b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
4665b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
4675b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
4685b003df0Sstefano_zampini 
4695b003df0Sstefano_zampini     /* attach local fields to the matrix */
4705b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
4715b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
4725b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
4735b003df0Sstefano_zampini       PetscInt n,st;
4745b003df0Sstefano_zampini 
4755b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
4765b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
4775b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
4785b003df0Sstefano_zampini     }
4795b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
4805b003df0Sstefano_zampini       PetscInt n,st;
4815b003df0Sstefano_zampini 
4825b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
4835b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
4845b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
4855b003df0Sstefano_zampini     }
4865b003df0Sstefano_zampini     lf->nr = nr;
4875b003df0Sstefano_zampini     lf->nc = nc;
4885b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
4895b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
4905b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
4915b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
4925b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
4935b003df0Sstefano_zampini   }
4945b003df0Sstefano_zampini 
4955e3038f0Sstefano_zampini   /* Free workspace */
4965e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4975e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
4985e3038f0Sstefano_zampini   }
4995e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
5005e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
5015e3038f0Sstefano_zampini   }
5029e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
5035b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
5045e3038f0Sstefano_zampini   PetscFunctionReturn(0);
5055e3038f0Sstefano_zampini }
5065e3038f0Sstefano_zampini 
5075e3038f0Sstefano_zampini #undef __FUNCT__
508ad219c80Sstefano_zampini #define __FUNCT__ "MatDiagonalScale_IS"
509ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
510ad219c80Sstefano_zampini {
511ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
512ad219c80Sstefano_zampini   Vec               ll,rr;
513ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
514ad219c80Sstefano_zampini   PetscScalar       *x,*y;
515ad219c80Sstefano_zampini   PetscErrorCode    ierr;
516ad219c80Sstefano_zampini 
517ad219c80Sstefano_zampini   PetscFunctionBegin;
518ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
519ad219c80Sstefano_zampini   if (l) {
520ad219c80Sstefano_zampini     ll   = matis->y;
521ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
522ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
523ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
524ad219c80Sstefano_zampini   } else {
525ad219c80Sstefano_zampini     ll = NULL;
526ad219c80Sstefano_zampini   }
527ad219c80Sstefano_zampini   if (r) {
528ad219c80Sstefano_zampini     rr   = matis->x;
529ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
530ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
531ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
532ad219c80Sstefano_zampini   } else {
533ad219c80Sstefano_zampini     rr = NULL;
534ad219c80Sstefano_zampini   }
535ad219c80Sstefano_zampini   if (ll) {
536ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
537ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
538ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
539ad219c80Sstefano_zampini   }
540ad219c80Sstefano_zampini   if (rr) {
541ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
542ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
543ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
544ad219c80Sstefano_zampini   }
545ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
546ad219c80Sstefano_zampini   PetscFunctionReturn(0);
547ad219c80Sstefano_zampini }
548ad219c80Sstefano_zampini 
549ad219c80Sstefano_zampini #undef __FUNCT__
550b4319ba4SBarry Smith #define __FUNCT__ "MatGetInfo_IS"
551b4319ba4SBarry Smith static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
552b4319ba4SBarry Smith {
553b4319ba4SBarry Smith   Mat_IS         *matis = (Mat_IS*)A->data;
554b4319ba4SBarry Smith   MatInfo        info;
555b4319ba4SBarry Smith   PetscReal      isend[6],irecv[6];
556b4319ba4SBarry Smith   PetscInt       bs;
557b4319ba4SBarry Smith   PetscErrorCode ierr;
558b4319ba4SBarry Smith 
559b4319ba4SBarry Smith   PetscFunctionBegin;
560b4319ba4SBarry Smith   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
561b4319ba4SBarry Smith   if (matis->A->ops->getinfo) {
562b4319ba4SBarry Smith     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
563b4319ba4SBarry Smith     isend[0] = info.nz_used;
564b4319ba4SBarry Smith     isend[1] = info.nz_allocated;
565b4319ba4SBarry Smith     isend[2] = info.nz_unneeded;
566b4319ba4SBarry Smith     isend[3] = info.memory;
567b4319ba4SBarry Smith     isend[4] = info.mallocs;
568b4319ba4SBarry Smith   } else {
569b4319ba4SBarry Smith     isend[0] = 0.;
570b4319ba4SBarry Smith     isend[1] = 0.;
571b4319ba4SBarry Smith     isend[2] = 0.;
572b4319ba4SBarry Smith     isend[3] = 0.;
573b4319ba4SBarry Smith     isend[4] = 0.;
574b4319ba4SBarry Smith   }
575b4319ba4SBarry Smith   isend[5] = matis->A->num_ass;
576b4319ba4SBarry Smith   if (flag == MAT_LOCAL) {
577b4319ba4SBarry Smith     ginfo->nz_used      = isend[0];
578b4319ba4SBarry Smith     ginfo->nz_allocated = isend[1];
579b4319ba4SBarry Smith     ginfo->nz_unneeded  = isend[2];
580b4319ba4SBarry Smith     ginfo->memory       = isend[3];
581b4319ba4SBarry Smith     ginfo->mallocs      = isend[4];
582b4319ba4SBarry Smith     ginfo->assemblies   = isend[5];
583b4319ba4SBarry Smith   } else if (flag == MAT_GLOBAL_MAX) {
584b4319ba4SBarry Smith     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
585b4319ba4SBarry Smith 
586b4319ba4SBarry Smith     ginfo->nz_used      = irecv[0];
587b4319ba4SBarry Smith     ginfo->nz_allocated = irecv[1];
588b4319ba4SBarry Smith     ginfo->nz_unneeded  = irecv[2];
589b4319ba4SBarry Smith     ginfo->memory       = irecv[3];
590b4319ba4SBarry Smith     ginfo->mallocs      = irecv[4];
591b4319ba4SBarry Smith     ginfo->assemblies   = irecv[5];
592b4319ba4SBarry Smith   } else if (flag == MAT_GLOBAL_SUM) {
593b4319ba4SBarry Smith     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
594b4319ba4SBarry Smith 
595b4319ba4SBarry Smith     ginfo->nz_used      = irecv[0];
596b4319ba4SBarry Smith     ginfo->nz_allocated = irecv[1];
597b4319ba4SBarry Smith     ginfo->nz_unneeded  = irecv[2];
598b4319ba4SBarry Smith     ginfo->memory       = irecv[3];
599b4319ba4SBarry Smith     ginfo->mallocs      = irecv[4];
600b4319ba4SBarry Smith     ginfo->assemblies   = A->num_ass;
601b4319ba4SBarry Smith   }
602b4319ba4SBarry Smith   ginfo->block_size        = bs;
603b4319ba4SBarry Smith   ginfo->fill_ratio_given  = 0;
604b4319ba4SBarry Smith   ginfo->fill_ratio_needed = 0;
605b4319ba4SBarry Smith   ginfo->factor_mallocs    = 0;
606a8116848SStefano Zampini   PetscFunctionReturn(0);
607a8116848SStefano Zampini }
608a8116848SStefano Zampini 
609a8116848SStefano Zampini #undef __FUNCT__
610b4319ba4SBarry Smith #define __FUNCT__ "MatTranspose_IS"
611b4319ba4SBarry Smith PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
612b4319ba4SBarry Smith {
613b4319ba4SBarry Smith   Mat                    C,lC,lA;
614b4319ba4SBarry Smith   PetscErrorCode         ierr;
615b4319ba4SBarry Smith 
616b4319ba4SBarry Smith   PetscFunctionBegin;
617*cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
618*cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
619b4319ba4SBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
620b4319ba4SBarry Smith     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
621b4319ba4SBarry Smith     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
622b4319ba4SBarry Smith     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
623b4319ba4SBarry Smith     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
624b4319ba4SBarry Smith     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
625*cf37664fSBarry Smith   } else {
626*cf37664fSBarry Smith     C = *B;
627b4319ba4SBarry Smith   }
628b4319ba4SBarry Smith 
629b4319ba4SBarry Smith   /* perform local transposition */
630b4319ba4SBarry Smith   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
631b4319ba4SBarry Smith   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
632b4319ba4SBarry Smith   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
633b4319ba4SBarry Smith   ierr = MatDestroy(&lC);CHKERRQ(ierr);
634b4319ba4SBarry Smith 
635*cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
636b4319ba4SBarry Smith     *B = C;
637b4319ba4SBarry Smith   } else {
638b4319ba4SBarry Smith     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
639b4319ba4SBarry Smith   }
640b4319ba4SBarry Smith   PetscFunctionReturn(0);
641b4319ba4SBarry Smith }
642b4319ba4SBarry Smith 
643b4319ba4SBarry Smith #undef __FUNCT__
644b4319ba4SBarry Smith #define __FUNCT__ "MatDiagonalSet_IS"
645b4319ba4SBarry Smith PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
646b4319ba4SBarry Smith {
647b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
648b4319ba4SBarry Smith   PetscErrorCode ierr;
649b4319ba4SBarry Smith 
650b4319ba4SBarry Smith   PetscFunctionBegin;
651b4319ba4SBarry Smith   if (!D) { /* this code branch is used by MatShift_IS */
652b4319ba4SBarry Smith     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
653b4319ba4SBarry Smith   } else {
654b4319ba4SBarry Smith     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
655b4319ba4SBarry Smith     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
656b4319ba4SBarry Smith   }
657b4319ba4SBarry Smith   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
658b4319ba4SBarry Smith   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
659b4319ba4SBarry Smith   PetscFunctionReturn(0);
660b4319ba4SBarry Smith }
661b4319ba4SBarry Smith 
662b4319ba4SBarry Smith #undef __FUNCT__
663b4319ba4SBarry Smith #define __FUNCT__ "MatShift_IS"
664b4319ba4SBarry Smith PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
665b4319ba4SBarry Smith {
666b4319ba4SBarry Smith   PetscErrorCode ierr;
667b4319ba4SBarry Smith 
668b4319ba4SBarry Smith   PetscFunctionBegin;
669b4319ba4SBarry Smith   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
670b4319ba4SBarry Smith   PetscFunctionReturn(0);
671b4319ba4SBarry Smith }
672b4319ba4SBarry Smith 
673b4319ba4SBarry Smith #undef __FUNCT__
674b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_SubMat_IS"
675b4319ba4SBarry Smith static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
676b4319ba4SBarry Smith {
677b4319ba4SBarry Smith   PetscErrorCode ierr;
678b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
679b4319ba4SBarry Smith   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
680b4319ba4SBarry Smith 
681b4319ba4SBarry Smith   PetscFunctionBegin;
682b4319ba4SBarry Smith #if defined(PETSC_USE_DEBUG)
683b4319ba4SBarry Smith   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);
684b4319ba4SBarry Smith #endif
685b4319ba4SBarry Smith   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
686b4319ba4SBarry Smith   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
687b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
688b4319ba4SBarry Smith   PetscFunctionReturn(0);
689b4319ba4SBarry Smith }
690b4319ba4SBarry Smith 
691b4319ba4SBarry Smith #undef __FUNCT__
692b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS"
693b4319ba4SBarry Smith static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
694b4319ba4SBarry Smith {
695b4319ba4SBarry Smith   PetscErrorCode ierr;
696b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
697b4319ba4SBarry Smith   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
698b4319ba4SBarry Smith 
699b4319ba4SBarry Smith   PetscFunctionBegin;
700b4319ba4SBarry Smith #if defined(PETSC_USE_DEBUG)
701b4319ba4SBarry Smith   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);
702b4319ba4SBarry Smith #endif
703b4319ba4SBarry Smith   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
70428f4e0baSStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
70528f4e0baSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
706a8116848SStefano Zampini   PetscFunctionReturn(0);
707a8116848SStefano Zampini }
708a8116848SStefano Zampini 
709a8116848SStefano Zampini #undef __FUNCT__
710a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private"
711a8116848SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
712a8116848SStefano Zampini {
713a8116848SStefano Zampini   PetscInt      *owners = map->range;
714a8116848SStefano Zampini   PetscInt       n      = map->n;
715a8116848SStefano Zampini   PetscSF        sf;
716a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
717a8116848SStefano Zampini   PetscSFNode   *ridxs;
718a8116848SStefano Zampini   PetscMPIInt    rank;
719a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
720a8116848SStefano Zampini   PetscErrorCode ierr;
721a8116848SStefano Zampini 
722a8116848SStefano Zampini   PetscFunctionBegin;
723fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
724a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
725a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
726a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
727a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
728a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
729a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
730a8116848SStefano Zampini     const PetscInt idx = idxs[r];
731a8116848SStefano 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);
732a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
733a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
734a8116848SStefano Zampini     }
735a8116848SStefano Zampini     ridxs[r].rank = p;
736a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
737a8116848SStefano Zampini   }
738a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
739a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
740a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
741a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
742a8116848SStefano Zampini   if (ogidxs) { /* communicate global idxs */
743a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
744a8116848SStefano Zampini 
745a8116848SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
746a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
747a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
748a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
749a8116848SStefano Zampini     start -= cum;
750a8116848SStefano Zampini     cum = 0;
751a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
752a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
753a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
754a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
755a8116848SStefano Zampini   }
756a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
757a8116848SStefano Zampini   /* Compress and put in indices */
758a8116848SStefano Zampini   for (r = 0; r < n; ++r)
759a8116848SStefano Zampini     if (lidxs[r] >= 0) {
760a8116848SStefano Zampini       if (work) work[len] = work[r];
761a8116848SStefano Zampini       lidxs[len++] = r;
762a8116848SStefano Zampini     }
763a8116848SStefano Zampini   if (on) *on = len;
764a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
765a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
766a8116848SStefano Zampini   PetscFunctionReturn(0);
767a8116848SStefano Zampini }
768a8116848SStefano Zampini 
769a8116848SStefano Zampini #undef __FUNCT__
770a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS"
771a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
772a8116848SStefano Zampini {
773a8116848SStefano Zampini   Mat               locmat,newlocmat;
774a8116848SStefano Zampini   Mat_IS            *newmatis;
775a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
776a8116848SStefano Zampini   Vec               rtest,ltest;
777a8116848SStefano Zampini   const PetscScalar *array;
778a8116848SStefano Zampini #endif
779a8116848SStefano Zampini   const PetscInt    *idxs;
780a8116848SStefano Zampini   PetscInt          i,m,n;
781a8116848SStefano Zampini   PetscErrorCode    ierr;
782a8116848SStefano Zampini 
783a8116848SStefano Zampini   PetscFunctionBegin;
784a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
785a8116848SStefano Zampini     PetscBool ismatis;
786a8116848SStefano Zampini 
787a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
788a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
789a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
790a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
791a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
792a8116848SStefano Zampini   }
793a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
794a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
795a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
796a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
797a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
798a8116848SStefano Zampini   for (i=0;i<n;i++) {
799a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
800a8116848SStefano Zampini   }
801a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
802a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
803a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
804a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
805a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
806a8116848SStefano Zampini   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]));
807a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
808a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
809a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
810a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
811a8116848SStefano Zampini   for (i=0;i<n;i++) {
812a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
813a8116848SStefano Zampini   }
814a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
815a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
816a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
817a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
818a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
819a8116848SStefano Zampini   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]));
820a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
821a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
822a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
823a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
824a8116848SStefano Zampini #endif
825a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
826a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
827a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
828a8116848SStefano Zampini     IS                     is;
829a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
830a8116848SStefano Zampini     PetscInt               ll,newloc;
831a8116848SStefano Zampini     MPI_Comm               comm;
832a8116848SStefano Zampini 
833a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
834a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
835a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
836a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
837a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
838a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
839a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
840a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
841a8116848SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
842a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
8433d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
8443d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
845a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
846a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
847a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
848a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
849a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
8503d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
851a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
852a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8533d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
854a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
855a8116848SStefano Zampini         lidxs[newloc] = i;
856a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
857a8116848SStefano Zampini       }
858a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
859a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
860a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
861a8116848SStefano Zampini     /* local is to extract local submatrix */
862a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
863a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
864a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
865a8116848SStefano Zampini       PetscBool cong;
866a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
867a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
868a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
869a8116848SStefano Zampini     }
870a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
871a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
872a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
873a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
874a8116848SStefano Zampini     } else {
875a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
876a8116848SStefano Zampini 
877a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
878a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
879f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
880a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
8813d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
882a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
883a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
884a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
885a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
886a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
8873d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
888a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
889a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8903d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
891a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
892a8116848SStefano Zampini           lidxs[newloc] = i;
893a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
894a8116848SStefano Zampini         }
895a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
896a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
897a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
898a8116848SStefano Zampini       /* local is to extract local submatrix */
899a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
900a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
901a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
902a8116848SStefano Zampini     }
903a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
904a8116848SStefano Zampini   } else {
905a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
906a8116848SStefano Zampini   }
907a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
908a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
909a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
910a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
911a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
912a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
913a8116848SStefano Zampini   }
914a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
915a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
916a8116848SStefano Zampini   PetscFunctionReturn(0);
917a8116848SStefano Zampini }
918a8116848SStefano Zampini 
919a8116848SStefano Zampini #undef __FUNCT__
9202b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS"
921a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
9222b404112SStefano Zampini {
9232b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
9242b404112SStefano Zampini   PetscBool      ismatis;
9252b404112SStefano Zampini   PetscErrorCode ierr;
9262b404112SStefano Zampini 
9272b404112SStefano Zampini   PetscFunctionBegin;
9282b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
9292b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
9302b404112SStefano Zampini   b = (Mat_IS*)B->data;
9312b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
9322b404112SStefano Zampini   PetscFunctionReturn(0);
9332b404112SStefano Zampini }
9342b404112SStefano Zampini 
9352b404112SStefano Zampini #undef __FUNCT__
9366bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS"
937a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
9386bd84002SStefano Zampini {
939527b2640SStefano Zampini   Vec               v;
940527b2640SStefano Zampini   const PetscScalar *array;
941527b2640SStefano Zampini   PetscInt          i,n;
9426bd84002SStefano Zampini   PetscErrorCode    ierr;
9436bd84002SStefano Zampini 
9446bd84002SStefano Zampini   PetscFunctionBegin;
945527b2640SStefano Zampini   *missing = PETSC_FALSE;
946527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
947527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
948527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
949527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
950527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
951527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
952527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
953527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
954527b2640SStefano Zampini   if (d) {
955527b2640SStefano Zampini     *d = -1;
956527b2640SStefano Zampini     if (*missing) {
957527b2640SStefano Zampini       PetscInt rstart;
958527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
959527b2640SStefano Zampini       *d = i+rstart;
960527b2640SStefano Zampini     }
961527b2640SStefano Zampini   }
9626bd84002SStefano Zampini   PetscFunctionReturn(0);
9636bd84002SStefano Zampini }
9646bd84002SStefano Zampini 
9656bd84002SStefano Zampini #undef __FUNCT__
966cf0a3239SStefano Zampini #define __FUNCT__ "MatISSetUpSF_IS"
967cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
96828f4e0baSStefano Zampini {
96928f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
97028f4e0baSStefano Zampini   const PetscInt *gidxs;
9714f2d7cafSStefano Zampini   PetscInt       nleaves;
97228f4e0baSStefano Zampini   PetscErrorCode ierr;
97328f4e0baSStefano Zampini 
97428f4e0baSStefano Zampini   PetscFunctionBegin;
9754f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
97628f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
9773bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9784f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
9794f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
9803bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9814f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
982a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
9833d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
984a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
985a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9863d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
987a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9883d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
989a8116848SStefano Zampini   } else {
990a8116848SStefano Zampini     matis->csf = matis->sf;
991a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
992a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
993a8116848SStefano Zampini   }
99428f4e0baSStefano Zampini   PetscFunctionReturn(0);
99528f4e0baSStefano Zampini }
9962e1947a5SStefano Zampini 
9972e1947a5SStefano Zampini #undef __FUNCT__
9982e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
999eb82efa4SStefano Zampini /*@
1000a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1001a88811baSStefano Zampini 
1002a88811baSStefano Zampini    Collective on MPI_Comm
1003a88811baSStefano Zampini 
1004a88811baSStefano Zampini    Input Parameters:
1005a88811baSStefano Zampini +  B - the matrix
1006a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1007a88811baSStefano Zampini            (same value is used for all local rows)
1008a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1009a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1010a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1011a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1012a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1013a88811baSStefano Zampini            the diagonal entry even if it is zero.
1014a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1015a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1016a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1017a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1018a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1019a88811baSStefano Zampini            structure. The size of this array is equal to the number
1020a88811baSStefano Zampini            of local rows, i.e 'm'.
1021a88811baSStefano Zampini 
1022a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1023a88811baSStefano Zampini 
1024a88811baSStefano Zampini    Level: intermediate
1025a88811baSStefano Zampini 
1026a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1027a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1028a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1029a88811baSStefano Zampini 
1030a88811baSStefano Zampini .keywords: matrix
1031a88811baSStefano Zampini 
10323c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1033a88811baSStefano Zampini @*/
10342e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10352e1947a5SStefano Zampini {
10362e1947a5SStefano Zampini   PetscErrorCode ierr;
10372e1947a5SStefano Zampini 
10382e1947a5SStefano Zampini   PetscFunctionBegin;
10392e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
10402e1947a5SStefano Zampini   PetscValidType(B,1);
10412e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
10422e1947a5SStefano Zampini   PetscFunctionReturn(0);
10432e1947a5SStefano Zampini }
10442e1947a5SStefano Zampini 
10452e1947a5SStefano Zampini #undef __FUNCT__
10462e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
10477230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10482e1947a5SStefano Zampini {
10492e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
105028f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
10512e1947a5SStefano Zampini   PetscErrorCode ierr;
10522e1947a5SStefano Zampini 
10532e1947a5SStefano Zampini   PetscFunctionBegin;
10546c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1055cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
10564f2d7cafSStefano Zampini 
10574f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
10584f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
10594f2d7cafSStefano Zampini 
10604f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
10614f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
10624f2d7cafSStefano Zampini 
106328f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
106428f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
106528f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
106628f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
10674f2d7cafSStefano Zampini 
10684f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
106928f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
10704f2d7cafSStefano Zampini 
10714f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
107228f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10734f2d7cafSStefano Zampini 
10744f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
107528f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10762e1947a5SStefano Zampini   PetscFunctionReturn(0);
10772e1947a5SStefano Zampini }
1078b4319ba4SBarry Smith 
1079b4319ba4SBarry Smith #undef __FUNCT__
10803927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
10813927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
10823927de2eSStefano Zampini {
10833927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
10843927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1085ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
10863927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
10873927de2eSStefano Zampini   PetscInt        lrows,lcols;
10883927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
10893927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
10903927de2eSStefano Zampini   PetscBool       isdense,issbaij;
10913927de2eSStefano Zampini   PetscErrorCode  ierr;
10923927de2eSStefano Zampini 
10933927de2eSStefano Zampini   PetscFunctionBegin;
10943927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
10953927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
10963927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
10973927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
10983927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
10993927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1100ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1101ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
11027230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1103ecf5a873SStefano Zampini   } else {
1104ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1105ecf5a873SStefano Zampini   }
1106ecf5a873SStefano Zampini 
11073927de2eSStefano Zampini   if (issbaij) {
11083927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
11093927de2eSStefano Zampini   }
11103927de2eSStefano Zampini   /*
1111ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
11123927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
11133927de2eSStefano Zampini   */
1114cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
11153927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
11163927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
11173927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
11183927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
11193927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
11203927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
11213927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
11223927de2eSStefano Zampini       row_ownership[j] = i;
11233927de2eSStefano Zampini     }
11243927de2eSStefano Zampini   }
11257230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
11263927de2eSStefano Zampini 
11273927de2eSStefano Zampini   /*
11283927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
11293927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
11303927de2eSStefano Zampini   */
11313927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
11323927de2eSStefano Zampini   /* preallocation as a MATAIJ */
11333927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
11343927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
1135ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
11363927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
11373927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1138ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
11393927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11403927de2eSStefano Zampini           my_dnz[i] += 1;
11413927de2eSStefano Zampini         } else { /* offdiag block */
11423927de2eSStefano Zampini           my_onz[i] += 1;
11433927de2eSStefano Zampini         }
11443927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
11453927de2eSStefano Zampini         if (i != j) {
11463927de2eSStefano Zampini           owner = row_ownership[index_col];
11473927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
11483927de2eSStefano Zampini             my_dnz[j] += 1;
11493927de2eSStefano Zampini           } else {
11503927de2eSStefano Zampini             my_onz[j] += 1;
11513927de2eSStefano Zampini           }
11523927de2eSStefano Zampini         }
11533927de2eSStefano Zampini       }
11543927de2eSStefano Zampini     }
1155bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1156bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1157bb1015c3SStefano Zampini     PetscBool      done;
1158bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1159bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1160bb1015c3SStefano Zampini     jptr = jj;
1161bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1162bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1163bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1164bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1165bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1166bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1167bb1015c3SStefano Zampini           my_dnz[i] += 1;
1168bb1015c3SStefano Zampini         } else { /* offdiag block */
1169bb1015c3SStefano Zampini           my_onz[i] += 1;
1170bb1015c3SStefano Zampini         }
1171bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1172bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1173bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1174bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1175bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1176bb1015c3SStefano Zampini           } else {
1177bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1178bb1015c3SStefano Zampini           }
1179bb1015c3SStefano Zampini         }
1180bb1015c3SStefano Zampini       }
1181bb1015c3SStefano Zampini     }
1182bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1183bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1184bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
11853927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
11863927de2eSStefano Zampini       const PetscInt *cols;
1187ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
11883927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11893927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
11903927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1191ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
11923927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11933927de2eSStefano Zampini           my_dnz[i] += 1;
11943927de2eSStefano Zampini         } else { /* offdiag block */
11953927de2eSStefano Zampini           my_onz[i] += 1;
11963927de2eSStefano Zampini         }
11973927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1198d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
11993927de2eSStefano Zampini           owner = row_ownership[index_col];
12003927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1201d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
12023927de2eSStefano Zampini           } else {
1203d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
12043927de2eSStefano Zampini           }
12053927de2eSStefano Zampini         }
12063927de2eSStefano Zampini       }
12073927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
12083927de2eSStefano Zampini     }
12093927de2eSStefano Zampini   }
1210ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1211ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
12127230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1213ecf5a873SStefano Zampini   }
12143927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1215ecf5a873SStefano Zampini 
1216ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
12173927de2eSStefano Zampini   if (maxreduce) {
12183927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
12193927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1220bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
12213927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
12223927de2eSStefano Zampini   } else {
12233927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
12243927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1225bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
12263927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
12273927de2eSStefano Zampini   }
12283927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
12293927de2eSStefano Zampini 
12303927de2eSStefano Zampini   /* Resize preallocation if overestimated */
12313927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
12323927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
12333927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
12343927de2eSStefano Zampini   }
12351670daf9Sstefano_zampini 
12361670daf9Sstefano_zampini   /* Set preallocation */
12373927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
12383927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
12393927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
12403927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
12413927de2eSStefano Zampini   }
12423927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12433927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12443927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
12453927de2eSStefano Zampini   if (issbaij) {
12463927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
12473927de2eSStefano Zampini   }
12483927de2eSStefano Zampini   PetscFunctionReturn(0);
12493927de2eSStefano Zampini }
12503927de2eSStefano Zampini 
12513927de2eSStefano Zampini #undef __FUNCT__
1252b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
12537230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1254b7ce53b6SStefano Zampini {
1255b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1256d9a9e74cSStefano Zampini   Mat            local_mat;
1257b7ce53b6SStefano Zampini   /* info on mat */
12583cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1259b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1260b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1261b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1262b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1263b9ed4604SStefano Zampini #endif
12647c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1265b7ce53b6SStefano Zampini   /* values insertion */
1266b7ce53b6SStefano Zampini   PetscScalar    *array;
1267b7ce53b6SStefano Zampini   /* work */
1268b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1269b7ce53b6SStefano Zampini 
1270b7ce53b6SStefano Zampini   PetscFunctionBegin;
1271b7ce53b6SStefano Zampini   /* get info from mat */
12727c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
12737c03b4e8SStefano Zampini   if (nsubdomains == 1) {
12741670daf9Sstefano_zampini     Mat            B;
12751670daf9Sstefano_zampini     IS             rows,cols;
1276acdf38a7Sstefano_zampini     IS             irows,icols;
12771670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
12781670daf9Sstefano_zampini 
12791670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
12801670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
12811670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
12821670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
12831670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
12841670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1285acdf38a7Sstefano_zampini     ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1286acdf38a7Sstefano_zampini     ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1287acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr);
1288acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr);
1289acdf38a7Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
1290acdf38a7Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
1291acdf38a7Sstefano_zampini     ierr = MatConvert(matis->A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
1292acdf38a7Sstefano_zampini     ierr = MatGetSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1293acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1294acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1295acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
12967c03b4e8SStefano Zampini     PetscFunctionReturn(0);
12977c03b4e8SStefano Zampini   }
1298b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1299b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
13003cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1301b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1302b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
1303686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1304b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1305b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1306b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1307b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1308b9ed4604SStefano Zampini   lb[0] = isseqdense;
1309b9ed4604SStefano Zampini   lb[1] = isseqaij;
1310b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1311b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1312b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1313b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1314b9ed4604SStefano Zampini #endif
1315b7ce53b6SStefano Zampini 
1316b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
13173927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
13183cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
13193927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
1320b9ed4604SStefano Zampini     if (!isseqsbaij) {
1321b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1322b9ed4604SStefano Zampini     } else {
1323b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1324b9ed4604SStefano Zampini     }
13253927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1326b7ce53b6SStefano Zampini   } else {
13273cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1328b7ce53b6SStefano Zampini     /* some checks */
1329b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1330b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
13313cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
13326c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
13336c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
13346c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
13356c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
13366c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1337b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1338b7ce53b6SStefano Zampini   }
1339d9a9e74cSStefano Zampini 
1340b9ed4604SStefano Zampini   if (isseqsbaij) {
1341d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1342d9a9e74cSStefano Zampini   } else {
1343d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1344d9a9e74cSStefano Zampini     local_mat = matis->A;
1345d9a9e74cSStefano Zampini   }
1346686e3a49SStefano Zampini 
1347b7ce53b6SStefano Zampini   /* Set values */
1348ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1349b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
1350ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
1351ecf5a873SStefano Zampini 
1352ecf5a873SStefano Zampini     if (local_rows != local_cols) {
1353ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
1354ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1355ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
1356ecf5a873SStefano Zampini     } else {
1357ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
1358ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1359ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
1360ecf5a873SStefano Zampini     }
1361b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1362d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
1363ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
1364d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
1365ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
1366ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
1367ecf5a873SStefano Zampini     } else {
1368ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
1369ecf5a873SStefano Zampini     }
1370686e3a49SStefano Zampini   } else if (isseqaij) {
1371ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1372686e3a49SStefano Zampini     PetscBool done;
1373686e3a49SStefano Zampini 
1374d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1375bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1376d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1377686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1378ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1379686e3a49SStefano Zampini     }
1380d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1381bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1382d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1383686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1384ecf5a873SStefano Zampini     PetscInt i;
1385c0962df8SStefano Zampini 
1386686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1387686e3a49SStefano Zampini       PetscInt       j;
1388ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1389686e3a49SStefano Zampini 
1390ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1391ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1392ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1393686e3a49SStefano Zampini     }
1394b7ce53b6SStefano Zampini   }
1395b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1396d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1397b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1398b9ed4604SStefano Zampini   if (isseqdense) {
1399b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1400b7ce53b6SStefano Zampini   }
1401b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1402b7ce53b6SStefano Zampini }
1403b7ce53b6SStefano Zampini 
1404b7ce53b6SStefano Zampini #undef __FUNCT__
1405b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
1406b7ce53b6SStefano Zampini /*@
1407b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1408b7ce53b6SStefano Zampini 
1409b7ce53b6SStefano Zampini   Input Parameter:
1410b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1411b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1412b7ce53b6SStefano Zampini 
1413b7ce53b6SStefano Zampini   Output Parameter:
1414b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1415b7ce53b6SStefano Zampini 
1416b7ce53b6SStefano Zampini   Level: developer
1417b7ce53b6SStefano Zampini 
1418eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1419b7ce53b6SStefano Zampini 
1420b7ce53b6SStefano Zampini .seealso: MATIS
1421b7ce53b6SStefano Zampini @*/
1422b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1423b7ce53b6SStefano Zampini {
1424b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1425b7ce53b6SStefano Zampini 
1426b7ce53b6SStefano Zampini   PetscFunctionBegin;
1427b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1428b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1429b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1430b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1431b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1432b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
14336c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1434b7ce53b6SStefano Zampini   }
1435b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1436b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1437b7ce53b6SStefano Zampini }
1438b7ce53b6SStefano Zampini 
1439b7ce53b6SStefano Zampini #undef __FUNCT__
1440ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
1441ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1442ad6194a2SStefano Zampini {
1443ad6194a2SStefano Zampini   PetscErrorCode ierr;
1444ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1445ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1446ad6194a2SStefano Zampini   Mat            B,localmat;
1447ad6194a2SStefano Zampini 
1448ad6194a2SStefano Zampini   PetscFunctionBegin;
1449ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1450ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1451ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1452e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1453ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1454ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1455b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1456ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1457ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1458ad6194a2SStefano Zampini   *newmat = B;
1459ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1460ad6194a2SStefano Zampini }
1461ad6194a2SStefano Zampini 
1462ad6194a2SStefano Zampini #undef __FUNCT__
146369796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
1464a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
146569796d55SStefano Zampini {
146669796d55SStefano Zampini   PetscErrorCode ierr;
146769796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
146869796d55SStefano Zampini   PetscBool      local_sym;
146969796d55SStefano Zampini 
147069796d55SStefano Zampini   PetscFunctionBegin;
147169796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1472b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
147369796d55SStefano Zampini   PetscFunctionReturn(0);
147469796d55SStefano Zampini }
147569796d55SStefano Zampini 
147669796d55SStefano Zampini #undef __FUNCT__
147769796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
1478a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
147969796d55SStefano Zampini {
148069796d55SStefano Zampini   PetscErrorCode ierr;
148169796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
148269796d55SStefano Zampini   PetscBool      local_sym;
148369796d55SStefano Zampini 
148469796d55SStefano Zampini   PetscFunctionBegin;
148569796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1486b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
148769796d55SStefano Zampini   PetscFunctionReturn(0);
148869796d55SStefano Zampini }
148969796d55SStefano Zampini 
149069796d55SStefano Zampini #undef __FUNCT__
149145471136SStefano Zampini #define __FUNCT__ "MatIsStructurallySymmetric_IS"
149245471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
149345471136SStefano Zampini {
149445471136SStefano Zampini   PetscErrorCode ierr;
149545471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
149645471136SStefano Zampini   PetscBool      local_sym;
149745471136SStefano Zampini 
149845471136SStefano Zampini   PetscFunctionBegin;
149945471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
150045471136SStefano Zampini     *flg = PETSC_FALSE;
150145471136SStefano Zampini     PetscFunctionReturn(0);
150245471136SStefano Zampini   }
150345471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
150445471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
150545471136SStefano Zampini   PetscFunctionReturn(0);
150645471136SStefano Zampini }
150745471136SStefano Zampini 
150845471136SStefano Zampini #undef __FUNCT__
1509b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
1510a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1511b4319ba4SBarry Smith {
1512dfbe8321SBarry Smith   PetscErrorCode ierr;
1513b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1514b4319ba4SBarry Smith 
1515b4319ba4SBarry Smith   PetscFunctionBegin;
15166bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1517e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1518e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
15196bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
15206bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
15213fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1522a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1523a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1524a8116848SStefano Zampini   if (b->sf != b->csf) {
1525a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1526a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1527a8116848SStefano Zampini   }
152828f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
152928f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1530bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1531dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1532bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1533b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1534b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
15352e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1536cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1537b4319ba4SBarry Smith   PetscFunctionReturn(0);
1538b4319ba4SBarry Smith }
1539b4319ba4SBarry Smith 
1540b4319ba4SBarry Smith #undef __FUNCT__
1541b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
1542a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1543b4319ba4SBarry Smith {
1544dfbe8321SBarry Smith   PetscErrorCode ierr;
1545b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1546b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1547b4319ba4SBarry Smith 
1548b4319ba4SBarry Smith   PetscFunctionBegin;
1549b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1550e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1551e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1552b4319ba4SBarry Smith 
1553b4319ba4SBarry Smith   /* multiply the local matrix */
1554b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1555b4319ba4SBarry Smith 
1556b4319ba4SBarry Smith   /* scatter product back into global memory */
15572dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1558e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1559e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1560b4319ba4SBarry Smith   PetscFunctionReturn(0);
1561b4319ba4SBarry Smith }
1562b4319ba4SBarry Smith 
1563b4319ba4SBarry Smith #undef __FUNCT__
15642e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
1565a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15662e74eeadSLisandro Dalcin {
1567650997f4SStefano Zampini   Vec            temp_vec;
15682e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15692e74eeadSLisandro Dalcin 
15702e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1571650997f4SStefano Zampini   if (v3 != v2) {
1572650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1573650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1574650997f4SStefano Zampini   } else {
1575650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1576650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1577650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1578650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1579650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1580650997f4SStefano Zampini   }
15812e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15822e74eeadSLisandro Dalcin }
15832e74eeadSLisandro Dalcin 
15842e74eeadSLisandro Dalcin #undef __FUNCT__
15852e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
1586a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
15872e74eeadSLisandro Dalcin {
15882e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
15892e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15902e74eeadSLisandro Dalcin 
1591e176bc59SStefano Zampini   PetscFunctionBegin;
15922e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1593e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1594e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15952e74eeadSLisandro Dalcin 
15962e74eeadSLisandro Dalcin   /* multiply the local matrix */
1597e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
15982e74eeadSLisandro Dalcin 
15992e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1600e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1601e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1602e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16032e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
16042e74eeadSLisandro Dalcin }
16052e74eeadSLisandro Dalcin 
16062e74eeadSLisandro Dalcin #undef __FUNCT__
16072e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
1608a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
16092e74eeadSLisandro Dalcin {
1610650997f4SStefano Zampini   Vec            temp_vec;
16112e74eeadSLisandro Dalcin   PetscErrorCode ierr;
16122e74eeadSLisandro Dalcin 
16132e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1614650997f4SStefano Zampini   if (v3 != v2) {
1615650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1616650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1617650997f4SStefano Zampini   } else {
1618650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1619650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1620650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1621650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1622650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1623650997f4SStefano Zampini   }
16242e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
16252e74eeadSLisandro Dalcin }
16262e74eeadSLisandro Dalcin 
16272e74eeadSLisandro Dalcin #undef __FUNCT__
1628b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
1629a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1630b4319ba4SBarry Smith {
1631b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1632dfbe8321SBarry Smith   PetscErrorCode ierr;
1633b4319ba4SBarry Smith   PetscViewer    sviewer;
1634ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1635b4319ba4SBarry Smith 
1636b4319ba4SBarry Smith   PetscFunctionBegin;
1637ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1638ee2491ecSStefano Zampini   if (isascii)  {
1639ee2491ecSStefano Zampini     PetscViewerFormat format;
1640ee2491ecSStefano Zampini 
1641ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1642ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1643ee2491ecSStefano Zampini   }
1644ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
16453f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1646b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
16473f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
16486e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1649b4319ba4SBarry Smith   PetscFunctionReturn(0);
1650b4319ba4SBarry Smith }
1651b4319ba4SBarry Smith 
1652b4319ba4SBarry Smith #undef __FUNCT__
1653b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
1654a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1655b4319ba4SBarry Smith {
1656dfbe8321SBarry Smith   PetscErrorCode ierr;
1657e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1658b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1659b4319ba4SBarry Smith   IS             from,to;
1660e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1661b4319ba4SBarry Smith 
1662b4319ba4SBarry Smith   PetscFunctionBegin;
1663784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1664e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
16653bbff08aSStefano Zampini   /* Destroy any previous data */
166670cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
166770cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
16683fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1669e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1670e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
16711c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
167228f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
167328f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
16743bbff08aSStefano Zampini 
16753bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1676fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1677fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1678fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1679fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1680b4319ba4SBarry Smith 
1681b4319ba4SBarry Smith   /* Create the local matrix A */
1682e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1683e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1684e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1685e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1686f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1687e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1688e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1689e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1690ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1691ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1692b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1693b4319ba4SBarry Smith 
1694f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1695b4319ba4SBarry Smith     /* Create the local work vectors */
16963bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1697b4319ba4SBarry Smith 
1698e176bc59SStefano Zampini     /* setup the global to local scatters */
1699e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1700e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1701784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1702e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1703e176bc59SStefano Zampini     if (rmapping != cmapping) {
1704e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1705e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1706e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1707e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1708e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1709e176bc59SStefano Zampini     } else {
1710e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1711e176bc59SStefano Zampini       is->cctx = is->rctx;
1712e176bc59SStefano Zampini     }
17133fd1c9e7SStefano Zampini 
17143fd1c9e7SStefano Zampini     /* interface counter vector (local) */
17153fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
17163fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
17173fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17183fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17193fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17203fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17213fd1c9e7SStefano Zampini 
17223fd1c9e7SStefano Zampini     /* free workspace */
1723e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1724e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
17256bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
17266bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1727f26d0771SStefano Zampini   }
172848ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1729b4319ba4SBarry Smith   PetscFunctionReturn(0);
1730b4319ba4SBarry Smith }
1731b4319ba4SBarry Smith 
17322e74eeadSLisandro Dalcin #undef __FUNCT__
17332e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
1734a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
17352e74eeadSLisandro Dalcin {
17362e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
17372e74eeadSLisandro Dalcin   PetscErrorCode ierr;
173897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
173997563a80SStefano Zampini   PetscInt       i,zm,zn;
174097563a80SStefano Zampini #endif
1741f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
17422e74eeadSLisandro Dalcin 
17432e74eeadSLisandro Dalcin   PetscFunctionBegin;
17442e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1745f26d0771SStefano 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);
174697563a80SStefano Zampini   /* count negative indices */
174797563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
174897563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
17492e74eeadSLisandro Dalcin #endif
175097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
175197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
175297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
175397563a80SStefano Zampini   /* count negative indices (should be the same as before) */
175497563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
175597563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
175697563a80SStefano 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");
175797563a80SStefano 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");
175897563a80SStefano Zampini #endif
17592e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
17602e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
17612e74eeadSLisandro Dalcin }
17622e74eeadSLisandro Dalcin 
1763b4319ba4SBarry Smith #undef __FUNCT__
176497563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS"
1765a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
176697563a80SStefano Zampini {
176797563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
176897563a80SStefano Zampini   PetscErrorCode ierr;
176997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
177097563a80SStefano Zampini   PetscInt       i,zm,zn;
177197563a80SStefano Zampini #endif
1772f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
177397563a80SStefano Zampini 
177497563a80SStefano Zampini   PetscFunctionBegin;
177597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1776f26d0771SStefano 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);
177797563a80SStefano Zampini   /* count negative indices */
177897563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
177997563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
178097563a80SStefano Zampini #endif
178197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
178297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
178397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
178497563a80SStefano Zampini   /* count negative indices (should be the same as before) */
178597563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
178697563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
178797563a80SStefano 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");
178897563a80SStefano 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");
178997563a80SStefano Zampini #endif
179097563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
179197563a80SStefano Zampini   PetscFunctionReturn(0);
179297563a80SStefano Zampini }
179397563a80SStefano Zampini 
179497563a80SStefano Zampini #undef __FUNCT__
1795b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
1796a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1797b4319ba4SBarry Smith {
1798dfbe8321SBarry Smith   PetscErrorCode ierr;
1799b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1800b4319ba4SBarry Smith 
1801b4319ba4SBarry Smith   PetscFunctionBegin;
1802b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1803b4319ba4SBarry Smith   PetscFunctionReturn(0);
1804b4319ba4SBarry Smith }
1805b4319ba4SBarry Smith 
1806b4319ba4SBarry Smith #undef __FUNCT__
1807f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
1808a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1809f0006bf2SLisandro Dalcin {
1810f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1811f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1812f0006bf2SLisandro Dalcin 
1813f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1814f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1815f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1816f0006bf2SLisandro Dalcin }
1817f0006bf2SLisandro Dalcin 
1818f0006bf2SLisandro Dalcin #undef __FUNCT__
1819f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private"
1820f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
1821f0ae7da4SStefano Zampini {
1822f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
1823f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1824f0ae7da4SStefano Zampini 
1825f0ae7da4SStefano Zampini   PetscFunctionBegin;
1826f0ae7da4SStefano Zampini   if (!n) {
1827f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1828f0ae7da4SStefano Zampini   } else {
1829f0ae7da4SStefano Zampini     PetscInt i;
1830f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1831f0ae7da4SStefano Zampini 
1832f0ae7da4SStefano Zampini     if (columns) {
1833f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1834f0ae7da4SStefano Zampini     } else {
1835f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1836f0ae7da4SStefano Zampini     }
1837f0ae7da4SStefano Zampini     if (diag != 0.) {
1838f0ae7da4SStefano Zampini       const PetscScalar *array;
1839f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1840f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1841f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1842f0ae7da4SStefano Zampini       }
1843f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1844f0ae7da4SStefano Zampini     }
1845f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1846f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1847f0ae7da4SStefano Zampini   }
1848f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1849f0ae7da4SStefano Zampini }
1850f0ae7da4SStefano Zampini 
1851f0ae7da4SStefano Zampini #undef __FUNCT__
1852f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS"
1853f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
18542e74eeadSLisandro Dalcin {
18556e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
18566e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
18576e520ac8SStefano Zampini   PetscInt       *lrows;
18582e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18592e74eeadSLisandro Dalcin 
18602e74eeadSLisandro Dalcin   PetscFunctionBegin;
1861f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1862f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1863f0ae7da4SStefano Zampini     PetscBool cong;
1864f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1865f0ae7da4SStefano 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");
1866f0ae7da4SStefano 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");
1867f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1868f0ae7da4SStefano Zampini   }
1869f0ae7da4SStefano Zampini #endif
18706e520ac8SStefano Zampini   /* get locally owned rows */
1871f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
18726e520ac8SStefano Zampini   /* fix right hand side if needed */
18736e520ac8SStefano Zampini   if (x && b) {
18746e520ac8SStefano Zampini     const PetscScalar *xx;
18756e520ac8SStefano Zampini     PetscScalar       *bb;
18766e520ac8SStefano Zampini 
18776e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
18786e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
18796e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
18806e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
18816e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
18822e74eeadSLisandro Dalcin   }
18836e520ac8SStefano Zampini   /* get rows associated to the local matrices */
18843d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
18856e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
18866e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
18876e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
18886e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
18896e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18906e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18916e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18926e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
18936e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1894f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
18956e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18962e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18972e74eeadSLisandro Dalcin }
18982e74eeadSLisandro Dalcin 
18992e74eeadSLisandro Dalcin #undef __FUNCT__
1900f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS"
1901f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1902b4319ba4SBarry Smith {
1903dfbe8321SBarry Smith   PetscErrorCode ierr;
1904b4319ba4SBarry Smith 
1905b4319ba4SBarry Smith   PetscFunctionBegin;
1906f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1907f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1908f0ae7da4SStefano Zampini }
19092205254eSKarl Rupp 
1910f0ae7da4SStefano Zampini #undef __FUNCT__
1911f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS"
1912f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1913f0ae7da4SStefano Zampini {
1914f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1915f0ae7da4SStefano Zampini 
1916f0ae7da4SStefano Zampini   PetscFunctionBegin;
1917f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1918b4319ba4SBarry Smith   PetscFunctionReturn(0);
1919b4319ba4SBarry Smith }
1920b4319ba4SBarry Smith 
1921b4319ba4SBarry Smith #undef __FUNCT__
1922b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
1923a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1924b4319ba4SBarry Smith {
1925b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1926dfbe8321SBarry Smith   PetscErrorCode ierr;
1927b4319ba4SBarry Smith 
1928b4319ba4SBarry Smith   PetscFunctionBegin;
1929b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1930b4319ba4SBarry Smith   PetscFunctionReturn(0);
1931b4319ba4SBarry Smith }
1932b4319ba4SBarry Smith 
1933b4319ba4SBarry Smith #undef __FUNCT__
1934b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
1935a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1936b4319ba4SBarry Smith {
1937b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1938dfbe8321SBarry Smith   PetscErrorCode ierr;
1939b4319ba4SBarry Smith 
1940b4319ba4SBarry Smith   PetscFunctionBegin;
1941b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1942b4319ba4SBarry Smith   PetscFunctionReturn(0);
1943b4319ba4SBarry Smith }
1944b4319ba4SBarry Smith 
1945b4319ba4SBarry Smith #undef __FUNCT__
1946b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
1947a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1948b4319ba4SBarry Smith {
1949b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1950b4319ba4SBarry Smith 
1951b4319ba4SBarry Smith   PetscFunctionBegin;
1952b4319ba4SBarry Smith   *local = is->A;
1953b4319ba4SBarry Smith   PetscFunctionReturn(0);
1954b4319ba4SBarry Smith }
1955b4319ba4SBarry Smith 
1956b4319ba4SBarry Smith #undef __FUNCT__
1957b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
1958b4319ba4SBarry Smith /*@
1959b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1960b4319ba4SBarry Smith 
1961b4319ba4SBarry Smith   Input Parameter:
1962b4319ba4SBarry Smith .  mat - the matrix
1963b4319ba4SBarry Smith 
1964b4319ba4SBarry Smith   Output Parameter:
1965eb82efa4SStefano Zampini .  local - the local matrix
1966b4319ba4SBarry Smith 
1967b4319ba4SBarry Smith   Level: advanced
1968b4319ba4SBarry Smith 
1969b4319ba4SBarry Smith   Notes:
1970b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1971b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1972b4319ba4SBarry Smith   of the MatSetValues() operation.
1973b4319ba4SBarry Smith 
1974b4319ba4SBarry Smith .seealso: MATIS
1975b4319ba4SBarry Smith @*/
19767087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1977b4319ba4SBarry Smith {
19784ac538c5SBarry Smith   PetscErrorCode ierr;
1979b4319ba4SBarry Smith 
1980b4319ba4SBarry Smith   PetscFunctionBegin;
19810700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1982b4319ba4SBarry Smith   PetscValidPointer(local,2);
19834ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1984b4319ba4SBarry Smith   PetscFunctionReturn(0);
1985b4319ba4SBarry Smith }
1986b4319ba4SBarry Smith 
19873b03a366Sstefano_zampini #undef __FUNCT__
19883b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
1989a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
19903b03a366Sstefano_zampini {
19913b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
19923b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
19933b03a366Sstefano_zampini   PetscErrorCode ierr;
19943b03a366Sstefano_zampini 
19953b03a366Sstefano_zampini   PetscFunctionBegin;
19964e4c7dbeSStefano Zampini   if (is->A) {
19973b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
19983b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1999f0ae7da4SStefano 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);
20004e4c7dbeSStefano Zampini   }
20013b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
20023b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
20033b03a366Sstefano_zampini   is->A = local;
20043b03a366Sstefano_zampini   PetscFunctionReturn(0);
20053b03a366Sstefano_zampini }
20063b03a366Sstefano_zampini 
20073b03a366Sstefano_zampini #undef __FUNCT__
20083b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
20093b03a366Sstefano_zampini /*@
2010eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
20113b03a366Sstefano_zampini 
20123b03a366Sstefano_zampini   Input Parameter:
20133b03a366Sstefano_zampini .  mat - the matrix
2014eb82efa4SStefano Zampini .  local - the local matrix
20153b03a366Sstefano_zampini 
20163b03a366Sstefano_zampini   Output Parameter:
20173b03a366Sstefano_zampini 
20183b03a366Sstefano_zampini   Level: advanced
20193b03a366Sstefano_zampini 
20203b03a366Sstefano_zampini   Notes:
20213b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
20223b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
20233b03a366Sstefano_zampini 
20243b03a366Sstefano_zampini .seealso: MATIS
20253b03a366Sstefano_zampini @*/
20263b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
20273b03a366Sstefano_zampini {
20283b03a366Sstefano_zampini   PetscErrorCode ierr;
20293b03a366Sstefano_zampini 
20303b03a366Sstefano_zampini   PetscFunctionBegin;
20313b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2032b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
20333b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
20343b03a366Sstefano_zampini   PetscFunctionReturn(0);
20353b03a366Sstefano_zampini }
20363b03a366Sstefano_zampini 
20376726f965SBarry Smith #undef __FUNCT__
20386726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
2039a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
20406726f965SBarry Smith {
20416726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
20426726f965SBarry Smith   PetscErrorCode ierr;
20436726f965SBarry Smith 
20446726f965SBarry Smith   PetscFunctionBegin;
20456726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
20466726f965SBarry Smith   PetscFunctionReturn(0);
20476726f965SBarry Smith }
20486726f965SBarry Smith 
20496726f965SBarry Smith #undef __FUNCT__
20502e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
2051a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
20522e74eeadSLisandro Dalcin {
20532e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20542e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20552e74eeadSLisandro Dalcin 
20562e74eeadSLisandro Dalcin   PetscFunctionBegin;
20572e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
20582e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20592e74eeadSLisandro Dalcin }
20602e74eeadSLisandro Dalcin 
20612e74eeadSLisandro Dalcin #undef __FUNCT__
20622e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
2063a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
20642e74eeadSLisandro Dalcin {
20652e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20662e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20672e74eeadSLisandro Dalcin 
20682e74eeadSLisandro Dalcin   PetscFunctionBegin;
20692e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
2070e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
20712e74eeadSLisandro Dalcin 
20722e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
20732e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
2074e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2075e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20762e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20772e74eeadSLisandro Dalcin }
20782e74eeadSLisandro Dalcin 
20792e74eeadSLisandro Dalcin #undef __FUNCT__
20806726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
2081a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
20826726f965SBarry Smith {
20836726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
20846726f965SBarry Smith   PetscErrorCode ierr;
20856726f965SBarry Smith 
20866726f965SBarry Smith   PetscFunctionBegin;
20874e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
20886726f965SBarry Smith   PetscFunctionReturn(0);
20896726f965SBarry Smith }
20906726f965SBarry Smith 
2091284134d9SBarry Smith #undef __FUNCT__
2092f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS"
2093f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
2094f26d0771SStefano Zampini {
2095f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
2096f26d0771SStefano Zampini   Mat_IS         *x;
2097f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2098f26d0771SStefano Zampini   PetscBool      ismatis;
2099f26d0771SStefano Zampini #endif
2100f26d0771SStefano Zampini   PetscErrorCode ierr;
2101f26d0771SStefano Zampini 
2102f26d0771SStefano Zampini   PetscFunctionBegin;
2103f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2104f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
2105f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
2106f26d0771SStefano Zampini #endif
2107f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
2108f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
2109f26d0771SStefano Zampini   PetscFunctionReturn(0);
2110f26d0771SStefano Zampini }
2111f26d0771SStefano Zampini 
2112f26d0771SStefano Zampini #undef __FUNCT__
2113f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS"
2114f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
2115f26d0771SStefano Zampini {
2116f26d0771SStefano Zampini   Mat                    lA;
2117f26d0771SStefano Zampini   Mat_IS                 *matis;
2118f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2119f26d0771SStefano Zampini   IS                     is;
2120f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
2121f26d0771SStefano Zampini   PetscInt               nrg;
2122f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
2123f26d0771SStefano Zampini   PetscErrorCode         ierr;
2124f26d0771SStefano Zampini 
2125f26d0771SStefano Zampini   PetscFunctionBegin;
2126f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2127f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
2128f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
2129f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
2130f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2131f0ae7da4SStefano 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);
2132f26d0771SStefano Zampini #endif
2133f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
2134f26d0771SStefano Zampini   /* map from [0,nrl) to row */
2135f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
2136f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2137f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
2138f26d0771SStefano Zampini #else
2139f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
2140f26d0771SStefano Zampini #endif
2141f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
2142f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2143f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2144f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2145f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
2146f26d0771SStefano Zampini   /* compute new l2g map for columns */
2147f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2148f26d0771SStefano Zampini     const PetscInt *cg,*cl;
2149f26d0771SStefano Zampini     PetscInt       ncg;
2150f26d0771SStefano Zampini     PetscInt       ncl;
2151f26d0771SStefano Zampini 
2152f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2153f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2154f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2155f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2156f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2157f0ae7da4SStefano 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);
2158f26d0771SStefano Zampini #endif
2159f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2160f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2161f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2162f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2163f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2164f26d0771SStefano Zampini #else
2165f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2166f26d0771SStefano Zampini #endif
2167f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2168f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2169f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2170f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2171f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2172f26d0771SStefano Zampini   } else {
2173f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2174f26d0771SStefano Zampini     cl2g = rl2g;
2175f26d0771SStefano Zampini   }
2176f26d0771SStefano Zampini   /* create the MATIS submatrix */
2177f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2178f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2179f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2180f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2181b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2182f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2183f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2184f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2185f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2186f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2187f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2188f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2189f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2190f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2191f26d0771SStefano Zampini   /* remove unsupported ops */
2192f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2193f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2194f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2195f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2196f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2197f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2198f26d0771SStefano Zampini   PetscFunctionReturn(0);
2199f26d0771SStefano Zampini }
2200f26d0771SStefano Zampini 
2201f26d0771SStefano Zampini #undef __FUNCT__
2202284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
2203284134d9SBarry Smith /*@
22043c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2205284134d9SBarry Smith        process but not across processes.
2206284134d9SBarry Smith 
2207284134d9SBarry Smith    Input Parameters:
2208284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2209e176bc59SStefano Zampini .     bs      - block size of the matrix
2210df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2211e176bc59SStefano Zampini .     rmap    - local to global map for rows
2212e176bc59SStefano Zampini -     cmap    - local to global map for cols
2213284134d9SBarry Smith 
2214284134d9SBarry Smith    Output Parameter:
2215284134d9SBarry Smith .    A - the resulting matrix
2216284134d9SBarry Smith 
22178e6c10adSSatish Balay    Level: advanced
22188e6c10adSSatish Balay 
22193c212e90SHong Zhang    Notes: See MATIS for more details.
22206fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
22216fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
22223c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2223284134d9SBarry Smith 
2224284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2225284134d9SBarry Smith @*/
2226e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2227284134d9SBarry Smith {
2228284134d9SBarry Smith   PetscErrorCode ierr;
2229284134d9SBarry Smith 
2230284134d9SBarry Smith   PetscFunctionBegin;
22316fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2232284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
22336fdf41d1SStefano Zampini   if (bs > 0) {
2234d3ee2243SStefano Zampini     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
22356fdf41d1SStefano Zampini   }
2236284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
2237284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2238e176bc59SStefano Zampini   if (rmap && cmap) {
2239e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2240e176bc59SStefano Zampini   } else if (!rmap) {
2241e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2242e176bc59SStefano Zampini   } else {
2243e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2244e176bc59SStefano Zampini   }
2245284134d9SBarry Smith   PetscFunctionReturn(0);
2246284134d9SBarry Smith }
2247284134d9SBarry Smith 
2248b4319ba4SBarry Smith /*MC
2249f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2250b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2251b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2252b4319ba4SBarry Smith    product is handled "implicitly".
2253b4319ba4SBarry Smith 
2254b4319ba4SBarry Smith    Operations Provided:
22556726f965SBarry Smith +  MatMult()
22562e74eeadSLisandro Dalcin .  MatMultAdd()
22572e74eeadSLisandro Dalcin .  MatMultTranspose()
22582e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
22596726f965SBarry Smith .  MatZeroEntries()
22606726f965SBarry Smith .  MatSetOption()
22612e74eeadSLisandro Dalcin .  MatZeroRows()
22622e74eeadSLisandro Dalcin .  MatSetValues()
226397563a80SStefano Zampini .  MatSetValuesBlocked()
22646726f965SBarry Smith .  MatSetValuesLocal()
226597563a80SStefano Zampini .  MatSetValuesBlockedLocal()
22662e74eeadSLisandro Dalcin .  MatScale()
22672e74eeadSLisandro Dalcin .  MatGetDiagonal()
22682b404112SStefano Zampini .  MatMissingDiagonal()
22692b404112SStefano Zampini .  MatDuplicate()
22702b404112SStefano Zampini .  MatCopy()
2271f26d0771SStefano Zampini .  MatAXPY()
2272f26d0771SStefano Zampini .  MatGetSubMatrix()
2273f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2274d7f69cd0SStefano Zampini .  MatTranspose()
22756726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2276b4319ba4SBarry Smith 
2277b4319ba4SBarry Smith    Options Database Keys:
2278b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2279b4319ba4SBarry Smith 
2280b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
2281b4319ba4SBarry Smith 
2282b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2283b4319ba4SBarry Smith 
2284b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2285eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2286b4319ba4SBarry Smith 
2287b4319ba4SBarry Smith   Level: advanced
2288b4319ba4SBarry Smith 
2289f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2290b4319ba4SBarry Smith 
2291b4319ba4SBarry Smith M*/
2292b4319ba4SBarry Smith 
2293b4319ba4SBarry Smith #undef __FUNCT__
2294b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
22958cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2296b4319ba4SBarry Smith {
2297dfbe8321SBarry Smith   PetscErrorCode ierr;
2298b4319ba4SBarry Smith   Mat_IS         *b;
2299b4319ba4SBarry Smith 
2300b4319ba4SBarry Smith   PetscFunctionBegin;
2301b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2302b4319ba4SBarry Smith   A->data = (void*)b;
2303b4319ba4SBarry Smith 
2304e176bc59SStefano Zampini   /* matrix ops */
2305e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2306b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
23072e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
23082e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
23092e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2310b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2311b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
23122e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
231398921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2314b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2315f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
23162e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2317f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2318b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2319b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2320b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
23216726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
23222e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
23232e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
23246726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
232569796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
232669796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
232745471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2328ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
23296bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
23302b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2331659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
2332a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
2333f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
23343fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
23353fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2336d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
23377fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
2338ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
2339b4319ba4SBarry Smith 
2340b7ce53b6SStefano Zampini   /* special MATIS functions */
2341bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
2342bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2343b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
23442e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2345cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
234617667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2347b4319ba4SBarry Smith   PetscFunctionReturn(0);
2348b4319ba4SBarry Smith }
2349