xref: /petsc/src/mat/impls/is/matis.c (revision ad219c80fb17c60796c2b918a4dd2ff21ebb63aa)
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 }
355b003df0Sstefano_zampini 
365b003df0Sstefano_zampini #undef __FUNCT__
375b003df0Sstefano_zampini #define __FUNCT__ "MatISContainerDestroyArray_Private"
385b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyArray_Private(void *ptr)
396989cf23SStefano Zampini {
406989cf23SStefano Zampini   PetscErrorCode ierr;
416989cf23SStefano Zampini 
426989cf23SStefano Zampini   PetscFunctionBeginUser;
436989cf23SStefano Zampini   ierr = PetscFree(ptr);CHKERRQ(ierr);
446989cf23SStefano Zampini   PetscFunctionReturn(0);
456989cf23SStefano Zampini }
466989cf23SStefano Zampini 
476989cf23SStefano Zampini #undef __FUNCT__
486989cf23SStefano Zampini #define __FUNCT__ "MatConvert_MPIAIJ_IS"
496989cf23SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
506989cf23SStefano Zampini {
516989cf23SStefano Zampini   Mat_MPIAIJ             *aij  = (Mat_MPIAIJ*)A->data;
526989cf23SStefano Zampini   Mat_SeqAIJ             *diag = (Mat_SeqAIJ*)(aij->A->data);
536989cf23SStefano Zampini   Mat_SeqAIJ             *offd = (Mat_SeqAIJ*)(aij->B->data);
546989cf23SStefano Zampini   Mat                    lA;
556989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
566989cf23SStefano Zampini   IS                     is;
576989cf23SStefano Zampini   MPI_Comm               comm;
586989cf23SStefano Zampini   void                   *ptrs[2];
596989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
606989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
616989cf23SStefano Zampini   PetscInt               *di,*dj,*oi,*oj;
626989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
63e363d98aSStefano Zampini   PetscInt               lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
646989cf23SStefano Zampini   PetscErrorCode         ierr;
656989cf23SStefano Zampini 
666989cf23SStefano Zampini   PetscFunctionBeginUser;
676989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
686989cf23SStefano Zampini   if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present");
696989cf23SStefano Zampini 
706989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
716989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
726989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
736989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
746989cf23SStefano Zampini   di   = diag->i;
756989cf23SStefano Zampini   dj   = diag->j;
766989cf23SStefano Zampini   dd   = diag->a;
776989cf23SStefano Zampini   oc   = aij->B->cmap->n;
786989cf23SStefano Zampini   oi   = offd->i;
796989cf23SStefano Zampini   oj   = offd->j;
806989cf23SStefano Zampini   od   = offd->a;
816989cf23SStefano Zampini   nnz  = diag->i[dr] + offd->i[dr];
826989cf23SStefano Zampini 
836989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
846989cf23SStefano Zampini   ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
856989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
866989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
87e363d98aSStefano Zampini   if (dr) {
886989cf23SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
896989cf23SStefano Zampini     for (i=0; i<dc; i++) aux[i]    = i+stc;
906989cf23SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i];
916989cf23SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
92e363d98aSStefano Zampini     lc   = dc+oc;
93e363d98aSStefano Zampini   } else {
94e363d98aSStefano Zampini     ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
95e363d98aSStefano Zampini     lc   = 0;
96e363d98aSStefano Zampini   }
976989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
986989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
996989cf23SStefano Zampini 
1006989cf23SStefano Zampini   /* create MATIS object */
1016989cf23SStefano Zampini   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1026989cf23SStefano Zampini   ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1036989cf23SStefano Zampini   ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1046989cf23SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1056989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1066989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1076989cf23SStefano Zampini 
1086989cf23SStefano Zampini   /* merge local matrices */
1096989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
1106989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
1116989cf23SStefano Zampini   ii   = aux;
1126989cf23SStefano Zampini   jj   = aux+dr+1;
1136989cf23SStefano Zampini   aa   = data;
1146989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
1156989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
1166989cf23SStefano Zampini   {
1176989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
1186989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
1196989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
1206989cf23SStefano Zampini   }
1216989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
1226989cf23SStefano Zampini   ii   = aux;
1236989cf23SStefano Zampini   jj   = aux+dr+1;
1246989cf23SStefano Zampini   aa   = data;
125e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
1266989cf23SStefano Zampini 
1276989cf23SStefano Zampini   /* create containers to destroy the data */
1286989cf23SStefano Zampini   ptrs[0] = aux;
1296989cf23SStefano Zampini   ptrs[1] = data;
1306989cf23SStefano Zampini   for (i=0; i<2; i++) {
1316989cf23SStefano Zampini     PetscContainer c;
1326989cf23SStefano Zampini 
1336989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
1346989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
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 {
168cf0a3239SStefano Zampini   PetscErrorCode ierr;
169cf0a3239SStefano Zampini 
170cf0a3239SStefano Zampini   PetscFunctionBegin;
171cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
172cf0a3239SStefano Zampini   PetscValidType(A,1);
173cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
174cf0a3239SStefano Zampini   PetscFunctionReturn(0);
175cf0a3239SStefano Zampini }
176a72627d2SStefano Zampini 
17728f4e0baSStefano Zampini #undef __FUNCT__
1785e3038f0Sstefano_zampini #define __FUNCT__ "MatConvert_Nest_IS"
1795e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1805e3038f0Sstefano_zampini {
1815e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
1825e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
1835e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
1845e3038f0Sstefano_zampini   MPI_Comm               comm;
1855b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
1865b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
1875e3038f0Sstefano_zampini   PetscBool              convert,lreuse;
1885e3038f0Sstefano_zampini   PetscErrorCode         ierr;
1895e3038f0Sstefano_zampini 
1905e3038f0Sstefano_zampini   PetscFunctionBeginUser;
1915e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
1925e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
1935e3038f0Sstefano_zampini   rnest  = NULL;
1945e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
1955e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
1965e3038f0Sstefano_zampini 
1975e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1985e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
1995e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
2005e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
2015e3038f0Sstefano_zampini     if (isnest) {
2025e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
2035e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
2045e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
2055e3038f0Sstefano_zampini     }
2065e3038f0Sstefano_zampini   }
2075e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
2085b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
2095e3038f0Sstefano_zampini   ierr = PetscCalloc5(nr,&isrow,nc,&iscol,
2105e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
2115e3038f0Sstefano_zampini                       nr*nc,&snest);CHKERRQ(ierr);
2125e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
2135e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2145e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2155e3038f0Sstefano_zampini       PetscBool ismatis;
2165e3038f0Sstefano_zampini       PetscInt  l1,l2,ij=i*nc+j;
2175e3038f0Sstefano_zampini 
2185e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
2195e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2205e3038f0Sstefano_zampini 
2215e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
2225e3038f0Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
2235e3038f0Sstefano_zampini       if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) is not of type MATIS",i,j);
2245e3038f0Sstefano_zampini 
2255e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
2265e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
2275e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
2285e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
2295e3038f0Sstefano_zampini       if (lr[i] && l1 != lr[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lr[i],l1);
2305e3038f0Sstefano_zampini       if (lc[j] && l2 != lc[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lc[j],l2);
2315e3038f0Sstefano_zampini       lr[i] = l1;
2325e3038f0Sstefano_zampini       lc[j] = l2;
2335e3038f0Sstefano_zampini 
2345e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
2355e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
2365e3038f0Sstefano_zampini     }
2375e3038f0Sstefano_zampini   }
2385e3038f0Sstefano_zampini 
2395e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
2405e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
2415e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
2425e3038f0Sstefano_zampini     rl2g = NULL;
2435e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
2445e3038f0Sstefano_zampini       PetscInt n1,n2;
2455e3038f0Sstefano_zampini 
2465e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
2475e3038f0Sstefano_zampini       ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
2485e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2495e3038f0Sstefano_zampini       if (!n1) continue;
2505e3038f0Sstefano_zampini       if (!rl2g) {
2515e3038f0Sstefano_zampini         rl2g = cl2g;
2525e3038f0Sstefano_zampini       } else {
2535e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2545e3038f0Sstefano_zampini         PetscBool      same;
2555e3038f0Sstefano_zampini 
2565e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2575e3038f0Sstefano_zampini         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap size %D != %D",i,j,n1,n2);
2585e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2595e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2605e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2615e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2625e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2635e3038f0Sstefano_zampini         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap",i,j);
2645e3038f0Sstefano_zampini       }
2655e3038f0Sstefano_zampini     }
2665e3038f0Sstefano_zampini   }
2675e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
2685e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
2695e3038f0Sstefano_zampini     rl2g = NULL;
2705e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
2715e3038f0Sstefano_zampini       PetscInt n1,n2;
2725e3038f0Sstefano_zampini 
2735e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
2745e3038f0Sstefano_zampini       ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
2755e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
2765e3038f0Sstefano_zampini       if (!n1) continue;
2775e3038f0Sstefano_zampini       if (!rl2g) {
2785e3038f0Sstefano_zampini         rl2g = cl2g;
2795e3038f0Sstefano_zampini       } else {
2805e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
2815e3038f0Sstefano_zampini         PetscBool      same;
2825e3038f0Sstefano_zampini 
2835e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
2845e3038f0Sstefano_zampini         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap size %D != %D",j,i,n1,n2);
2855e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
2865e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
2875e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
2885e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
2895e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
2905e3038f0Sstefano_zampini         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap",j,i);
2915e3038f0Sstefano_zampini       }
2925e3038f0Sstefano_zampini     }
2935e3038f0Sstefano_zampini   }
2945e3038f0Sstefano_zampini #endif
2955e3038f0Sstefano_zampini 
2965e3038f0Sstefano_zampini   B = NULL;
2975e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
2985b003df0Sstefano_zampini     PetscInt stl;
2995b003df0Sstefano_zampini 
3005e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
3015e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
3025e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3035b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
3045e3038f0Sstefano_zampini       Mat            usedmat;
3055e3038f0Sstefano_zampini       Mat_IS         *matis;
3065e3038f0Sstefano_zampini       const PetscInt *idxs;
3075e3038f0Sstefano_zampini 
3085e3038f0Sstefano_zampini       /* local IS for local NEST */
3095b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
3105e3038f0Sstefano_zampini 
3115e3038f0Sstefano_zampini       /* l2gmap */
3125e3038f0Sstefano_zampini       j = 0;
3135e3038f0Sstefano_zampini       usedmat = nest[i][j];
3145e3038f0Sstefano_zampini       while (!usedmat && j < nc) usedmat = nest[i][j++];
31582d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3165e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3175e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
3185e3038f0Sstefano_zampini       ierr  = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3195e3038f0Sstefano_zampini       ierr  = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3205e3038f0Sstefano_zampini       ierr  = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
3215e3038f0Sstefano_zampini       stl  += lr[i];
3225e3038f0Sstefano_zampini     }
3235e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
3245e3038f0Sstefano_zampini 
3255e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
3265e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
3275e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
3285b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
3295e3038f0Sstefano_zampini       Mat            usedmat;
3305e3038f0Sstefano_zampini       Mat_IS         *matis;
3315e3038f0Sstefano_zampini       const PetscInt *idxs;
3325e3038f0Sstefano_zampini 
3335e3038f0Sstefano_zampini       /* local IS for local NEST */
3345b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
3355e3038f0Sstefano_zampini 
3365e3038f0Sstefano_zampini       /* l2gmap */
3375e3038f0Sstefano_zampini       j = 0;
3385e3038f0Sstefano_zampini       usedmat = nest[j][i];
3395e3038f0Sstefano_zampini       while (!usedmat && j < nr) usedmat = nest[j++][i];
34082d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
3415e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
3425e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
3435e3038f0Sstefano_zampini       ierr  = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3445e3038f0Sstefano_zampini       ierr  = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
3455e3038f0Sstefano_zampini       ierr  = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
3465e3038f0Sstefano_zampini       stl  += lc[i];
3475e3038f0Sstefano_zampini     }
3485e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
3495e3038f0Sstefano_zampini 
3505e3038f0Sstefano_zampini     /* Create MATIS */
3515e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
3525e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
3535e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
3545e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
3555e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
3565e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
3575e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3585e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3595e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
3605e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
3615e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
3625e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3635e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3645e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
3655e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
3665e3038f0Sstefano_zampini     } else {
3675e3038f0Sstefano_zampini       *newmat = B;
3685e3038f0Sstefano_zampini     }
3695e3038f0Sstefano_zampini   } else {
3705e3038f0Sstefano_zampini     if (lreuse) {
3715e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
3725e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
3735e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
3745e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
3755e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
3765e3038f0Sstefano_zampini           }
3775e3038f0Sstefano_zampini         }
3785e3038f0Sstefano_zampini       }
3795e3038f0Sstefano_zampini     } else {
3805b003df0Sstefano_zampini       PetscInt stl;
3815b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
3825b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
3835b003df0Sstefano_zampini         stl  += lr[i];
3845e3038f0Sstefano_zampini       }
3855b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
3865b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
3875b003df0Sstefano_zampini         stl  += lc[i];
3885e3038f0Sstefano_zampini       }
3895e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
3905e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
3915e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
3925e3038f0Sstefano_zampini     }
3935e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3945e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3955e3038f0Sstefano_zampini   }
3965e3038f0Sstefano_zampini 
3975b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
3985b003df0Sstefano_zampini   convert = PETSC_FALSE;
3995b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
4005b003df0Sstefano_zampini   if (convert) {
4015b003df0Sstefano_zampini     Mat              M;
4025b003df0Sstefano_zampini     MatISLocalFields lf;
4035b003df0Sstefano_zampini     PetscContainer   c;
4045b003df0Sstefano_zampini 
4055b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4065b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
4075b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
4085b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
4095b003df0Sstefano_zampini 
4105b003df0Sstefano_zampini     /* attach local fields to the matrix */
4115b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
4125b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
4135b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
4145b003df0Sstefano_zampini       PetscInt n,st;
4155b003df0Sstefano_zampini 
4165b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
4175b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
4185b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
4195b003df0Sstefano_zampini     }
4205b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
4215b003df0Sstefano_zampini       PetscInt n,st;
4225b003df0Sstefano_zampini 
4235b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
4245b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
4255b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
4265b003df0Sstefano_zampini     }
4275b003df0Sstefano_zampini     lf->nr = nr;
4285b003df0Sstefano_zampini     lf->nc = nc;
4295b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
4305b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
4315b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
4325b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
4335b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
4345b003df0Sstefano_zampini   }
4355b003df0Sstefano_zampini 
4365e3038f0Sstefano_zampini   /* Free workspace */
4375e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4385e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
4395e3038f0Sstefano_zampini   }
4405e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
4415e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
4425e3038f0Sstefano_zampini   }
4435e3038f0Sstefano_zampini   ierr = PetscFree5(isrow,iscol,islrow,islcol,snest);CHKERRQ(ierr);
4445b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
4455e3038f0Sstefano_zampini   PetscFunctionReturn(0);
4465e3038f0Sstefano_zampini }
4475e3038f0Sstefano_zampini 
4485e3038f0Sstefano_zampini #undef __FUNCT__
449*ad219c80Sstefano_zampini #define __FUNCT__ "MatDiagonalScale_IS"
450*ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
451*ad219c80Sstefano_zampini {
452*ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
453*ad219c80Sstefano_zampini   Vec               ll,rr;
454*ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
455*ad219c80Sstefano_zampini   PetscScalar       *x,*y;
456*ad219c80Sstefano_zampini   PetscErrorCode    ierr;
457*ad219c80Sstefano_zampini 
458*ad219c80Sstefano_zampini   PetscFunctionBegin;
459*ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
460*ad219c80Sstefano_zampini   if (l) {
461*ad219c80Sstefano_zampini     ll   = matis->y;
462*ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
463*ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
464*ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
465*ad219c80Sstefano_zampini   } else {
466*ad219c80Sstefano_zampini     ll = NULL;
467*ad219c80Sstefano_zampini   }
468*ad219c80Sstefano_zampini   if (r) {
469*ad219c80Sstefano_zampini     rr   = matis->x;
470*ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
471*ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
472*ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
473*ad219c80Sstefano_zampini   } else {
474*ad219c80Sstefano_zampini     rr = NULL;
475*ad219c80Sstefano_zampini   }
476*ad219c80Sstefano_zampini   if (ll) {
477*ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
478*ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
479*ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
480*ad219c80Sstefano_zampini   }
481*ad219c80Sstefano_zampini   if (rr) {
482*ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
483*ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
484*ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
485*ad219c80Sstefano_zampini   }
486*ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
487*ad219c80Sstefano_zampini   PetscFunctionReturn(0);
488*ad219c80Sstefano_zampini }
489*ad219c80Sstefano_zampini 
490*ad219c80Sstefano_zampini #undef __FUNCT__
4917fa8f2d3SStefano Zampini #define __FUNCT__ "MatGetInfo_IS"
4927fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
4937fa8f2d3SStefano Zampini {
4947fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
4957fa8f2d3SStefano Zampini   MatInfo        info;
496314ce898Sstefano_zampini   PetscReal      isend[6],irecv[6];
4977fa8f2d3SStefano Zampini   PetscInt       bs;
4987fa8f2d3SStefano Zampini   PetscErrorCode ierr;
4997fa8f2d3SStefano Zampini 
5007fa8f2d3SStefano Zampini   PetscFunctionBegin;
5017fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
502a2ccb5f9Sstefano_zampini   if (matis->A->ops->getinfo) {
5037fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
5047fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
5057fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
5067fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
5077fa8f2d3SStefano Zampini     isend[3] = info.memory;
5087fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
509a2ccb5f9Sstefano_zampini   } else {
510a2ccb5f9Sstefano_zampini     isend[0] = 0.;
511a2ccb5f9Sstefano_zampini     isend[1] = 0.;
512a2ccb5f9Sstefano_zampini     isend[2] = 0.;
513a2ccb5f9Sstefano_zampini     isend[3] = 0.;
514a2ccb5f9Sstefano_zampini     isend[4] = 0.;
515a2ccb5f9Sstefano_zampini   }
516314ce898Sstefano_zampini   isend[5] = matis->A->num_ass;
5177fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
5187fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
5197fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
5207fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
5217fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
5227fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
523314ce898Sstefano_zampini     ginfo->assemblies   = isend[5];
5247fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
525314ce898Sstefano_zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
5267fa8f2d3SStefano Zampini 
5277fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
5287fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
5297fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
5307fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
5317fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
532314ce898Sstefano_zampini     ginfo->assemblies   = irecv[5];
5337fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
5347fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
5357fa8f2d3SStefano Zampini 
5367fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
5377fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
5387fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
5397fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
5407fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
5417fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
5427fa8f2d3SStefano Zampini   }
5437fa8f2d3SStefano Zampini   ginfo->block_size        = bs;
5447fa8f2d3SStefano Zampini   ginfo->fill_ratio_given  = 0;
5457fa8f2d3SStefano Zampini   ginfo->fill_ratio_needed = 0;
5467fa8f2d3SStefano Zampini   ginfo->factor_mallocs    = 0;
5477fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
5487fa8f2d3SStefano Zampini }
5497fa8f2d3SStefano Zampini 
5507fa8f2d3SStefano Zampini #undef __FUNCT__
551d7f69cd0SStefano Zampini #define __FUNCT__ "MatTranspose_IS"
552d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
553d7f69cd0SStefano Zampini {
554d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
555d7f69cd0SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
556d7f69cd0SStefano Zampini   PetscBool              notset = PETSC_FALSE,cong = PETSC_TRUE;
557d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
558d7f69cd0SStefano Zampini 
559d7f69cd0SStefano Zampini   PetscFunctionBegin;
560d7f69cd0SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
561d7f69cd0SStefano Zampini     PetscBool rcong,ccong;
562d7f69cd0SStefano Zampini 
563d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr);
564d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr);
565fa520230SStefano Zampini     cong = (PetscBool)(rcong || ccong);
566d7f69cd0SStefano Zampini   }
567d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) {
568d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
569d7f69cd0SStefano Zampini   } else {
570d7f69cd0SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,&notset);CHKERRQ(ierr);
571d7f69cd0SStefano Zampini     C = *B;
572d7f69cd0SStefano Zampini   }
573d7f69cd0SStefano Zampini 
574d7f69cd0SStefano Zampini   if (!notset) {
575d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
576d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
577d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
578d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
579d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
580d7f69cd0SStefano Zampini   }
581d7f69cd0SStefano Zampini 
582d7f69cd0SStefano Zampini   /* perform local transposition */
583d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
584d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
585d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
586d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
587d7f69cd0SStefano Zampini 
588d7f69cd0SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
589d7f69cd0SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
590d7f69cd0SStefano Zampini 
591d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
592d7f69cd0SStefano Zampini     if (!cong) {
593d7f69cd0SStefano Zampini       ierr = MatDestroy(B);CHKERRQ(ierr);
594d7f69cd0SStefano Zampini     }
595d7f69cd0SStefano Zampini     *B = C;
596d7f69cd0SStefano Zampini   } else {
597d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
598d7f69cd0SStefano Zampini   }
599d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
600d7f69cd0SStefano Zampini }
601d7f69cd0SStefano Zampini 
602d7f69cd0SStefano Zampini #undef __FUNCT__
6033fd1c9e7SStefano Zampini #define __FUNCT__ "MatDiagonalSet_IS"
6043fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
6053fd1c9e7SStefano Zampini {
6063fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
6073fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6083fd1c9e7SStefano Zampini 
6093fd1c9e7SStefano Zampini   PetscFunctionBegin;
6103fd1c9e7SStefano Zampini   if (!D) { /* this code branch is used by MatShift_IS */
6113fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
6123fd1c9e7SStefano Zampini   } else {
6133fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6143fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6153fd1c9e7SStefano Zampini   }
6163fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
6173fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
6183fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6193fd1c9e7SStefano Zampini }
6203fd1c9e7SStefano Zampini 
6213fd1c9e7SStefano Zampini #undef __FUNCT__
6223fd1c9e7SStefano Zampini #define __FUNCT__ "MatShift_IS"
6233fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
6243fd1c9e7SStefano Zampini {
6253fd1c9e7SStefano Zampini   PetscErrorCode ierr;
6263fd1c9e7SStefano Zampini 
6273fd1c9e7SStefano Zampini   PetscFunctionBegin;
6283fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
6293fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
6303fd1c9e7SStefano Zampini }
6313fd1c9e7SStefano Zampini 
6323fd1c9e7SStefano Zampini #undef __FUNCT__
633f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS"
634f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
635f26d0771SStefano Zampini {
636f26d0771SStefano Zampini   PetscErrorCode ierr;
637f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
638f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
639f26d0771SStefano Zampini 
640f26d0771SStefano Zampini   PetscFunctionBegin;
641f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
642f26d0771SStefano 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);
643f26d0771SStefano Zampini #endif
644f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
645f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
646f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
647f26d0771SStefano Zampini   PetscFunctionReturn(0);
648f26d0771SStefano Zampini }
649f26d0771SStefano Zampini 
650f26d0771SStefano Zampini #undef __FUNCT__
651f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS"
652f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
653f26d0771SStefano Zampini {
654f26d0771SStefano Zampini   PetscErrorCode ierr;
655f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
656f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
657f26d0771SStefano Zampini 
658f26d0771SStefano Zampini   PetscFunctionBegin;
659f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
660f26d0771SStefano 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);
661f26d0771SStefano Zampini #endif
662f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
663f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
664f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
665f26d0771SStefano Zampini   PetscFunctionReturn(0);
666f26d0771SStefano Zampini }
667f26d0771SStefano Zampini 
668f26d0771SStefano Zampini #undef __FUNCT__
669a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private"
670f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
671a8116848SStefano Zampini {
672a8116848SStefano Zampini   PetscInt      *owners = map->range;
673a8116848SStefano Zampini   PetscInt       n      = map->n;
674a8116848SStefano Zampini   PetscSF        sf;
675a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
676a8116848SStefano Zampini   PetscSFNode   *ridxs;
677a8116848SStefano Zampini   PetscMPIInt    rank;
678a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
679a8116848SStefano Zampini   PetscErrorCode ierr;
680a8116848SStefano Zampini 
681a8116848SStefano Zampini   PetscFunctionBegin;
682fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
683a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
684a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
685a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
686a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
687a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
688a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
689a8116848SStefano Zampini     const PetscInt idx = idxs[r];
690a8116848SStefano 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);
691a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
692a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
693a8116848SStefano Zampini     }
694a8116848SStefano Zampini     ridxs[r].rank = p;
695a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
696a8116848SStefano Zampini   }
697a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
698a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
699a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
700a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
701f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
702a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
703f0ae7da4SStefano Zampini 
704f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
705a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
706a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
707a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
708a8116848SStefano Zampini     start -= cum;
709a8116848SStefano Zampini     cum = 0;
710a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
711a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
712a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
713a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
714a8116848SStefano Zampini   }
715a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
716a8116848SStefano Zampini   /* Compress and put in indices */
717a8116848SStefano Zampini   for (r = 0; r < n; ++r)
718a8116848SStefano Zampini     if (lidxs[r] >= 0) {
719a8116848SStefano Zampini       if (work) work[len] = work[r];
720a8116848SStefano Zampini       lidxs[len++] = r;
721a8116848SStefano Zampini     }
722a8116848SStefano Zampini   if (on) *on = len;
723a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
724a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
725a8116848SStefano Zampini   PetscFunctionReturn(0);
726a8116848SStefano Zampini }
727a8116848SStefano Zampini 
728a8116848SStefano Zampini #undef __FUNCT__
729a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS"
730a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
731a8116848SStefano Zampini {
732a8116848SStefano Zampini   Mat               locmat,newlocmat;
733a8116848SStefano Zampini   Mat_IS            *newmatis;
734a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
735a8116848SStefano Zampini   Vec               rtest,ltest;
736a8116848SStefano Zampini   const PetscScalar *array;
737a8116848SStefano Zampini #endif
738a8116848SStefano Zampini   const PetscInt    *idxs;
739a8116848SStefano Zampini   PetscInt          i,m,n;
740a8116848SStefano Zampini   PetscErrorCode    ierr;
741a8116848SStefano Zampini 
742a8116848SStefano Zampini   PetscFunctionBegin;
743a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
744a8116848SStefano Zampini     PetscBool ismatis;
745a8116848SStefano Zampini 
746a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
747a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
748a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
749a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
750a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
751a8116848SStefano Zampini   }
752a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
753a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
754a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
755a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
756a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
757a8116848SStefano Zampini   for (i=0;i<n;i++) {
758a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
759a8116848SStefano Zampini   }
760a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
761a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
762a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
763a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
764a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
765fd479f66SMatthew G. Knepley   for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Irow may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
766a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
767a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
768a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
769a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
770a8116848SStefano Zampini   for (i=0;i<n;i++) {
771a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
772a8116848SStefano Zampini   }
773a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
774a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
775a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
776a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
777a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
778fd479f66SMatthew G. Knepley   for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Icol may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
779a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
780a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
781a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
782a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
783a8116848SStefano Zampini #endif
784a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
785a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
786a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
787a8116848SStefano Zampini     IS                     is;
788a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
7896dd40735SStefano Zampini     PetscInt               ll,newloc;
790a8116848SStefano Zampini     MPI_Comm               comm;
791a8116848SStefano Zampini 
792a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
793a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
794a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
795a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
796a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
797a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
798a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
799a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
800f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
801a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
8023d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
8033d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
804a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
805a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
806a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
807a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
808a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
8093d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
810a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
811a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8123d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
813a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
814a8116848SStefano Zampini         lidxs[newloc] = i;
815a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
816a8116848SStefano Zampini       }
817a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
818a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
819a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
820a8116848SStefano Zampini     /* local is to extract local submatrix */
821a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
822a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
823a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
824a8116848SStefano Zampini       PetscBool cong;
825a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
826a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
827a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
828a8116848SStefano Zampini     }
829a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
830a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
831a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
832a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
833a8116848SStefano Zampini     } else {
834a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
835a8116848SStefano Zampini 
836a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
837a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
838f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
839a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
8403d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
841a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
842a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
843a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
844a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
845a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
8463d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
847a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
848a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
8493d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
850a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
851a8116848SStefano Zampini           lidxs[newloc] = i;
852a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
853a8116848SStefano Zampini         }
854a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
855a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
856a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
857a8116848SStefano Zampini       /* local is to extract local submatrix */
858a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
859a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
860a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
861a8116848SStefano Zampini     }
862a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
863a8116848SStefano Zampini   } else {
864a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
865a8116848SStefano Zampini   }
866a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
867a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
868a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
869a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
870a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
871a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
872a8116848SStefano Zampini   }
873a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
874a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
875a8116848SStefano Zampini   PetscFunctionReturn(0);
876a8116848SStefano Zampini }
877a8116848SStefano Zampini 
878a8116848SStefano Zampini #undef __FUNCT__
8792b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS"
880a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
8812b404112SStefano Zampini {
8822b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
8832b404112SStefano Zampini   PetscBool      ismatis;
8842b404112SStefano Zampini   PetscErrorCode ierr;
8852b404112SStefano Zampini 
8862b404112SStefano Zampini   PetscFunctionBegin;
8872b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
8882b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
8892b404112SStefano Zampini   b = (Mat_IS*)B->data;
8902b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
8912b404112SStefano Zampini   PetscFunctionReturn(0);
8922b404112SStefano Zampini }
8932b404112SStefano Zampini 
8942b404112SStefano Zampini #undef __FUNCT__
8956bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS"
896a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
8976bd84002SStefano Zampini {
898527b2640SStefano Zampini   Vec               v;
899527b2640SStefano Zampini   const PetscScalar *array;
900527b2640SStefano Zampini   PetscInt          i,n;
9016bd84002SStefano Zampini   PetscErrorCode    ierr;
9026bd84002SStefano Zampini 
9036bd84002SStefano Zampini   PetscFunctionBegin;
904527b2640SStefano Zampini   *missing = PETSC_FALSE;
905527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
906527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
907527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
908527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
909527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
910527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
911527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
912527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
913527b2640SStefano Zampini   if (d) {
914527b2640SStefano Zampini     *d = -1;
915527b2640SStefano Zampini     if (*missing) {
916527b2640SStefano Zampini       PetscInt rstart;
917527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
918527b2640SStefano Zampini       *d = i+rstart;
919527b2640SStefano Zampini     }
920527b2640SStefano Zampini   }
9216bd84002SStefano Zampini   PetscFunctionReturn(0);
9226bd84002SStefano Zampini }
9236bd84002SStefano Zampini 
9246bd84002SStefano Zampini #undef __FUNCT__
925cf0a3239SStefano Zampini #define __FUNCT__ "MatISSetUpSF_IS"
926cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
92728f4e0baSStefano Zampini {
92828f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
92928f4e0baSStefano Zampini   const PetscInt *gidxs;
9304f2d7cafSStefano Zampini   PetscInt       nleaves;
93128f4e0baSStefano Zampini   PetscErrorCode ierr;
93228f4e0baSStefano Zampini 
93328f4e0baSStefano Zampini   PetscFunctionBegin;
9344f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
93528f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
9363bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9374f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
9384f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
9393bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
9404f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
941a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
9423d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
943a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
944a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9453d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
946a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
9473d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
948a8116848SStefano Zampini   } else {
949a8116848SStefano Zampini     matis->csf = matis->sf;
950a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
951a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
952a8116848SStefano Zampini   }
95328f4e0baSStefano Zampini   PetscFunctionReturn(0);
95428f4e0baSStefano Zampini }
9552e1947a5SStefano Zampini 
9562e1947a5SStefano Zampini #undef __FUNCT__
9572e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
958eb82efa4SStefano Zampini /*@
959a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
960a88811baSStefano Zampini 
961a88811baSStefano Zampini    Collective on MPI_Comm
962a88811baSStefano Zampini 
963a88811baSStefano Zampini    Input Parameters:
964a88811baSStefano Zampini +  B - the matrix
965a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
966a88811baSStefano Zampini            (same value is used for all local rows)
967a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
968a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
969a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
970a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
971a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
972a88811baSStefano Zampini            the diagonal entry even if it is zero.
973a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
974a88811baSStefano Zampini            submatrix (same value is used for all local rows).
975a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
976a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
977a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
978a88811baSStefano Zampini            structure. The size of this array is equal to the number
979a88811baSStefano Zampini            of local rows, i.e 'm'.
980a88811baSStefano Zampini 
981a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
982a88811baSStefano Zampini 
983a88811baSStefano Zampini    Level: intermediate
984a88811baSStefano Zampini 
985a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
986a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
987a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
988a88811baSStefano Zampini 
989a88811baSStefano Zampini .keywords: matrix
990a88811baSStefano Zampini 
9913c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
992a88811baSStefano Zampini @*/
9932e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
9942e1947a5SStefano Zampini {
9952e1947a5SStefano Zampini   PetscErrorCode ierr;
9962e1947a5SStefano Zampini 
9972e1947a5SStefano Zampini   PetscFunctionBegin;
9982e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
9992e1947a5SStefano Zampini   PetscValidType(B,1);
10002e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
10012e1947a5SStefano Zampini   PetscFunctionReturn(0);
10022e1947a5SStefano Zampini }
10032e1947a5SStefano Zampini 
10042e1947a5SStefano Zampini #undef __FUNCT__
10052e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
10067230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
10072e1947a5SStefano Zampini {
10082e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
100928f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
10102e1947a5SStefano Zampini   PetscErrorCode ierr;
10112e1947a5SStefano Zampini 
10122e1947a5SStefano Zampini   PetscFunctionBegin;
10136c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1014cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
10154f2d7cafSStefano Zampini 
10164f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
10174f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
10184f2d7cafSStefano Zampini 
10194f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
10204f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
10214f2d7cafSStefano Zampini 
102228f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
102328f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
102428f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
102528f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
10264f2d7cafSStefano Zampini 
10274f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
102828f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
10294f2d7cafSStefano Zampini 
10304f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
103128f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10324f2d7cafSStefano Zampini 
10334f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
103428f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
10352e1947a5SStefano Zampini   PetscFunctionReturn(0);
10362e1947a5SStefano Zampini }
1037b4319ba4SBarry Smith 
1038b4319ba4SBarry Smith #undef __FUNCT__
10393927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
10403927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
10413927de2eSStefano Zampini {
10423927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
10433927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1044ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
10453927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
10463927de2eSStefano Zampini   PetscInt        lrows,lcols;
10473927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
10483927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
10493927de2eSStefano Zampini   PetscBool       isdense,issbaij;
10503927de2eSStefano Zampini   PetscErrorCode  ierr;
10513927de2eSStefano Zampini 
10523927de2eSStefano Zampini   PetscFunctionBegin;
10533927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
10543927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
10553927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
10563927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
10573927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
10583927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1059ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1060ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
10617230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1062ecf5a873SStefano Zampini   } else {
1063ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1064ecf5a873SStefano Zampini   }
1065ecf5a873SStefano Zampini 
10663927de2eSStefano Zampini   if (issbaij) {
10673927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
10683927de2eSStefano Zampini   }
10693927de2eSStefano Zampini   /*
1070ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
10713927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
10723927de2eSStefano Zampini   */
1073cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
10743927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
10753927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
10763927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
10773927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
10783927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
10793927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
10803927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
10813927de2eSStefano Zampini       row_ownership[j] = i;
10823927de2eSStefano Zampini     }
10833927de2eSStefano Zampini   }
10847230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
10853927de2eSStefano Zampini 
10863927de2eSStefano Zampini   /*
10873927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
10883927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
10893927de2eSStefano Zampini   */
10903927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
10913927de2eSStefano Zampini   /* preallocation as a MATAIJ */
10923927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
10933927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
1094ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
10953927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
10963927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1097ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
10983927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
10993927de2eSStefano Zampini           my_dnz[i] += 1;
11003927de2eSStefano Zampini         } else { /* offdiag block */
11013927de2eSStefano Zampini           my_onz[i] += 1;
11023927de2eSStefano Zampini         }
11033927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
11043927de2eSStefano Zampini         if (i != j) {
11053927de2eSStefano Zampini           owner = row_ownership[index_col];
11063927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
11073927de2eSStefano Zampini             my_dnz[j] += 1;
11083927de2eSStefano Zampini           } else {
11093927de2eSStefano Zampini             my_onz[j] += 1;
11103927de2eSStefano Zampini           }
11113927de2eSStefano Zampini         }
11123927de2eSStefano Zampini       }
11133927de2eSStefano Zampini     }
1114bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1115bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1116bb1015c3SStefano Zampini     PetscBool      done;
1117bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1118bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1119bb1015c3SStefano Zampini     jptr = jj;
1120bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1121bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1122bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1123bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1124bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1125bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1126bb1015c3SStefano Zampini           my_dnz[i] += 1;
1127bb1015c3SStefano Zampini         } else { /* offdiag block */
1128bb1015c3SStefano Zampini           my_onz[i] += 1;
1129bb1015c3SStefano Zampini         }
1130bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1131bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1132bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1133bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1134bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1135bb1015c3SStefano Zampini           } else {
1136bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1137bb1015c3SStefano Zampini           }
1138bb1015c3SStefano Zampini         }
1139bb1015c3SStefano Zampini       }
1140bb1015c3SStefano Zampini     }
1141bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1142bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1143bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
11443927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
11453927de2eSStefano Zampini       const PetscInt *cols;
1146ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
11473927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11483927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
11493927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1150ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
11513927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
11523927de2eSStefano Zampini           my_dnz[i] += 1;
11533927de2eSStefano Zampini         } else { /* offdiag block */
11543927de2eSStefano Zampini           my_onz[i] += 1;
11553927de2eSStefano Zampini         }
11563927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1157d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
11583927de2eSStefano Zampini           owner = row_ownership[index_col];
11593927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1160d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
11613927de2eSStefano Zampini           } else {
1162d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
11633927de2eSStefano Zampini           }
11643927de2eSStefano Zampini         }
11653927de2eSStefano Zampini       }
11663927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
11673927de2eSStefano Zampini     }
11683927de2eSStefano Zampini   }
1169ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1170ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
11717230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1172ecf5a873SStefano Zampini   }
11733927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1174ecf5a873SStefano Zampini 
1175ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
11763927de2eSStefano Zampini   if (maxreduce) {
11773927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11783927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1179bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
11803927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
11813927de2eSStefano Zampini   } else {
11823927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
11833927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1184bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
11853927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
11863927de2eSStefano Zampini   }
11873927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
11883927de2eSStefano Zampini 
11893927de2eSStefano Zampini   /* Resize preallocation if overestimated */
11903927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
11913927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
11923927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
11933927de2eSStefano Zampini   }
11941670daf9Sstefano_zampini 
11951670daf9Sstefano_zampini   /* Set preallocation */
11963927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
11973927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
11983927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
11993927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
12003927de2eSStefano Zampini   }
12013927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12023927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
12033927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
12043927de2eSStefano Zampini   if (issbaij) {
12053927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
12063927de2eSStefano Zampini   }
12073927de2eSStefano Zampini   PetscFunctionReturn(0);
12083927de2eSStefano Zampini }
12093927de2eSStefano Zampini 
12103927de2eSStefano Zampini #undef __FUNCT__
1211b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
12127230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1213b7ce53b6SStefano Zampini {
1214b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1215d9a9e74cSStefano Zampini   Mat            local_mat;
1216b7ce53b6SStefano Zampini   /* info on mat */
12173cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1218b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1219b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1220b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1221b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1222b9ed4604SStefano Zampini #endif
12237c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1224b7ce53b6SStefano Zampini   /* values insertion */
1225b7ce53b6SStefano Zampini   PetscScalar    *array;
1226b7ce53b6SStefano Zampini   /* work */
1227b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1228b7ce53b6SStefano Zampini 
1229b7ce53b6SStefano Zampini   PetscFunctionBegin;
1230b7ce53b6SStefano Zampini   /* get info from mat */
12317c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
12327c03b4e8SStefano Zampini   if (nsubdomains == 1) {
12331670daf9Sstefano_zampini     Mat            B;
12341670daf9Sstefano_zampini     IS             rows,cols;
1235acdf38a7Sstefano_zampini     IS             irows,icols;
12361670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
12371670daf9Sstefano_zampini 
12381670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
12391670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
12401670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
12411670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
12421670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
12431670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1244acdf38a7Sstefano_zampini     ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1245acdf38a7Sstefano_zampini     ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1246acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr);
1247acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr);
1248acdf38a7Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
1249acdf38a7Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
1250acdf38a7Sstefano_zampini     ierr = MatConvert(matis->A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
1251acdf38a7Sstefano_zampini     ierr = MatGetSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1252acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1253acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1254acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
12557c03b4e8SStefano Zampini     PetscFunctionReturn(0);
12567c03b4e8SStefano Zampini   }
1257b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1258b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
12593cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1260b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1261b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
1262686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1263b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1264b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1265b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1266b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1267b9ed4604SStefano Zampini   lb[0] = isseqdense;
1268b9ed4604SStefano Zampini   lb[1] = isseqaij;
1269b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1270b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1271b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1272b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1273b9ed4604SStefano Zampini #endif
1274b7ce53b6SStefano Zampini 
1275b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
12763927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
12773cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
12783927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
1279b9ed4604SStefano Zampini     if (!isseqsbaij) {
1280b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1281b9ed4604SStefano Zampini     } else {
1282b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1283b9ed4604SStefano Zampini     }
12843927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1285b7ce53b6SStefano Zampini   } else {
12863cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1287b7ce53b6SStefano Zampini     /* some checks */
1288b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1289b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
12903cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
12916c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
12926c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
12936c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
12946c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
12956c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1296b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1297b7ce53b6SStefano Zampini   }
1298d9a9e74cSStefano Zampini 
1299b9ed4604SStefano Zampini   if (isseqsbaij) {
1300d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1301d9a9e74cSStefano Zampini   } else {
1302d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1303d9a9e74cSStefano Zampini     local_mat = matis->A;
1304d9a9e74cSStefano Zampini   }
1305686e3a49SStefano Zampini 
1306b7ce53b6SStefano Zampini   /* Set values */
1307ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1308b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
1309ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
1310ecf5a873SStefano Zampini 
1311ecf5a873SStefano Zampini     if (local_rows != local_cols) {
1312ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
1313ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1314ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
1315ecf5a873SStefano Zampini     } else {
1316ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
1317ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1318ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
1319ecf5a873SStefano Zampini     }
1320b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1321d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
1322ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
1323d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
1324ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
1325ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
1326ecf5a873SStefano Zampini     } else {
1327ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
1328ecf5a873SStefano Zampini     }
1329686e3a49SStefano Zampini   } else if (isseqaij) {
1330ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1331686e3a49SStefano Zampini     PetscBool done;
1332686e3a49SStefano Zampini 
1333d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1334bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1335d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1336686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1337ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1338686e3a49SStefano Zampini     }
1339d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1340bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1341d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1342686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1343ecf5a873SStefano Zampini     PetscInt i;
1344c0962df8SStefano Zampini 
1345686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1346686e3a49SStefano Zampini       PetscInt       j;
1347ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1348686e3a49SStefano Zampini 
1349ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1350ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1351ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1352686e3a49SStefano Zampini     }
1353b7ce53b6SStefano Zampini   }
1354b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1355d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1356b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1357b9ed4604SStefano Zampini   if (isseqdense) {
1358b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1359b7ce53b6SStefano Zampini   }
1360b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1361b7ce53b6SStefano Zampini }
1362b7ce53b6SStefano Zampini 
1363b7ce53b6SStefano Zampini #undef __FUNCT__
1364b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
1365b7ce53b6SStefano Zampini /*@
1366b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1367b7ce53b6SStefano Zampini 
1368b7ce53b6SStefano Zampini   Input Parameter:
1369b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1370b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1371b7ce53b6SStefano Zampini 
1372b7ce53b6SStefano Zampini   Output Parameter:
1373b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1374b7ce53b6SStefano Zampini 
1375b7ce53b6SStefano Zampini   Level: developer
1376b7ce53b6SStefano Zampini 
1377eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1378b7ce53b6SStefano Zampini 
1379b7ce53b6SStefano Zampini .seealso: MATIS
1380b7ce53b6SStefano Zampini @*/
1381b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1382b7ce53b6SStefano Zampini {
1383b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1384b7ce53b6SStefano Zampini 
1385b7ce53b6SStefano Zampini   PetscFunctionBegin;
1386b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1387b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1388b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1389b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1390b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1391b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
13926c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1393b7ce53b6SStefano Zampini   }
1394b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1395b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1396b7ce53b6SStefano Zampini }
1397b7ce53b6SStefano Zampini 
1398b7ce53b6SStefano Zampini #undef __FUNCT__
1399ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
1400ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1401ad6194a2SStefano Zampini {
1402ad6194a2SStefano Zampini   PetscErrorCode ierr;
1403ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1404ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1405ad6194a2SStefano Zampini   Mat            B,localmat;
1406ad6194a2SStefano Zampini 
1407ad6194a2SStefano Zampini   PetscFunctionBegin;
1408ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1409ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1410ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1411e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1412ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1413ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1414b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1415ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1416ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1417ad6194a2SStefano Zampini   *newmat = B;
1418ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1419ad6194a2SStefano Zampini }
1420ad6194a2SStefano Zampini 
1421ad6194a2SStefano Zampini #undef __FUNCT__
142269796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
1423a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
142469796d55SStefano Zampini {
142569796d55SStefano Zampini   PetscErrorCode ierr;
142669796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
142769796d55SStefano Zampini   PetscBool      local_sym;
142869796d55SStefano Zampini 
142969796d55SStefano Zampini   PetscFunctionBegin;
143069796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1431b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
143269796d55SStefano Zampini   PetscFunctionReturn(0);
143369796d55SStefano Zampini }
143469796d55SStefano Zampini 
143569796d55SStefano Zampini #undef __FUNCT__
143669796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
1437a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
143869796d55SStefano Zampini {
143969796d55SStefano Zampini   PetscErrorCode ierr;
144069796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
144169796d55SStefano Zampini   PetscBool      local_sym;
144269796d55SStefano Zampini 
144369796d55SStefano Zampini   PetscFunctionBegin;
144469796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1445b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
144669796d55SStefano Zampini   PetscFunctionReturn(0);
144769796d55SStefano Zampini }
144869796d55SStefano Zampini 
144969796d55SStefano Zampini #undef __FUNCT__
145045471136SStefano Zampini #define __FUNCT__ "MatIsStructurallySymmetric_IS"
145145471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
145245471136SStefano Zampini {
145345471136SStefano Zampini   PetscErrorCode ierr;
145445471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
145545471136SStefano Zampini   PetscBool      local_sym;
145645471136SStefano Zampini 
145745471136SStefano Zampini   PetscFunctionBegin;
145845471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
145945471136SStefano Zampini     *flg = PETSC_FALSE;
146045471136SStefano Zampini     PetscFunctionReturn(0);
146145471136SStefano Zampini   }
146245471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
146345471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
146445471136SStefano Zampini   PetscFunctionReturn(0);
146545471136SStefano Zampini }
146645471136SStefano Zampini 
146745471136SStefano Zampini #undef __FUNCT__
1468b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
1469a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1470b4319ba4SBarry Smith {
1471dfbe8321SBarry Smith   PetscErrorCode ierr;
1472b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1473b4319ba4SBarry Smith 
1474b4319ba4SBarry Smith   PetscFunctionBegin;
14756bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1476e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1477e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
14786bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
14796bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
14803fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1481a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1482a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1483a8116848SStefano Zampini   if (b->sf != b->csf) {
1484a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1485a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1486a8116848SStefano Zampini   }
148728f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
148828f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1489bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1490dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1491bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1492b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1493b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
14942e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1495cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1496b4319ba4SBarry Smith   PetscFunctionReturn(0);
1497b4319ba4SBarry Smith }
1498b4319ba4SBarry Smith 
1499b4319ba4SBarry Smith #undef __FUNCT__
1500b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
1501a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1502b4319ba4SBarry Smith {
1503dfbe8321SBarry Smith   PetscErrorCode ierr;
1504b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1505b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1506b4319ba4SBarry Smith 
1507b4319ba4SBarry Smith   PetscFunctionBegin;
1508b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1509e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1510e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1511b4319ba4SBarry Smith 
1512b4319ba4SBarry Smith   /* multiply the local matrix */
1513b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1514b4319ba4SBarry Smith 
1515b4319ba4SBarry Smith   /* scatter product back into global memory */
15162dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1517e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1518e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1519b4319ba4SBarry Smith   PetscFunctionReturn(0);
1520b4319ba4SBarry Smith }
1521b4319ba4SBarry Smith 
1522b4319ba4SBarry Smith #undef __FUNCT__
15232e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
1524a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15252e74eeadSLisandro Dalcin {
1526650997f4SStefano Zampini   Vec            temp_vec;
15272e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15282e74eeadSLisandro Dalcin 
15292e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1530650997f4SStefano Zampini   if (v3 != v2) {
1531650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1532650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1533650997f4SStefano Zampini   } else {
1534650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1535650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1536650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1537650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1538650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1539650997f4SStefano Zampini   }
15402e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15412e74eeadSLisandro Dalcin }
15422e74eeadSLisandro Dalcin 
15432e74eeadSLisandro Dalcin #undef __FUNCT__
15442e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
1545a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
15462e74eeadSLisandro Dalcin {
15472e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
15482e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15492e74eeadSLisandro Dalcin 
1550e176bc59SStefano Zampini   PetscFunctionBegin;
15512e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1552e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1553e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15542e74eeadSLisandro Dalcin 
15552e74eeadSLisandro Dalcin   /* multiply the local matrix */
1556e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
15572e74eeadSLisandro Dalcin 
15582e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1559e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1560e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1561e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15622e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15632e74eeadSLisandro Dalcin }
15642e74eeadSLisandro Dalcin 
15652e74eeadSLisandro Dalcin #undef __FUNCT__
15662e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
1567a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
15682e74eeadSLisandro Dalcin {
1569650997f4SStefano Zampini   Vec            temp_vec;
15702e74eeadSLisandro Dalcin   PetscErrorCode ierr;
15712e74eeadSLisandro Dalcin 
15722e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1573650997f4SStefano Zampini   if (v3 != v2) {
1574650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1575650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1576650997f4SStefano Zampini   } else {
1577650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1578650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1579650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1580650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1581650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1582650997f4SStefano Zampini   }
15832e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
15842e74eeadSLisandro Dalcin }
15852e74eeadSLisandro Dalcin 
15862e74eeadSLisandro Dalcin #undef __FUNCT__
1587b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
1588a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1589b4319ba4SBarry Smith {
1590b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1591dfbe8321SBarry Smith   PetscErrorCode ierr;
1592b4319ba4SBarry Smith   PetscViewer    sviewer;
1593ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1594b4319ba4SBarry Smith 
1595b4319ba4SBarry Smith   PetscFunctionBegin;
1596ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1597ee2491ecSStefano Zampini   if (isascii)  {
1598ee2491ecSStefano Zampini     PetscViewerFormat format;
1599ee2491ecSStefano Zampini 
1600ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1601ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1602ee2491ecSStefano Zampini   }
1603ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
16043f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1605b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
16063f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
16076e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1608b4319ba4SBarry Smith   PetscFunctionReturn(0);
1609b4319ba4SBarry Smith }
1610b4319ba4SBarry Smith 
1611b4319ba4SBarry Smith #undef __FUNCT__
1612b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
1613a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1614b4319ba4SBarry Smith {
1615dfbe8321SBarry Smith   PetscErrorCode ierr;
1616e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1617b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1618b4319ba4SBarry Smith   IS             from,to;
1619e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1620b4319ba4SBarry Smith 
1621b4319ba4SBarry Smith   PetscFunctionBegin;
1622784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1623e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
16243bbff08aSStefano Zampini   /* Destroy any previous data */
162570cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
162670cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
16273fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1628e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1629e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
16301c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
163128f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
163228f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
16333bbff08aSStefano Zampini 
16343bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1635fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1636fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1637fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1638fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1639b4319ba4SBarry Smith 
1640b4319ba4SBarry Smith   /* Create the local matrix A */
1641e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1642e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1643e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1644e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1645f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1646e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1647e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1648e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1649ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1650ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1651b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1652b4319ba4SBarry Smith 
1653f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1654b4319ba4SBarry Smith     /* Create the local work vectors */
16553bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1656b4319ba4SBarry Smith 
1657e176bc59SStefano Zampini     /* setup the global to local scatters */
1658e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1659e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1660784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1661e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1662e176bc59SStefano Zampini     if (rmapping != cmapping) {
1663e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1664e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1665e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1666e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1667e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1668e176bc59SStefano Zampini     } else {
1669e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1670e176bc59SStefano Zampini       is->cctx = is->rctx;
1671e176bc59SStefano Zampini     }
16723fd1c9e7SStefano Zampini 
16733fd1c9e7SStefano Zampini     /* interface counter vector (local) */
16743fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
16753fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
16763fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16773fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16783fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16793fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16803fd1c9e7SStefano Zampini 
16813fd1c9e7SStefano Zampini     /* free workspace */
1682e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1683e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
16846bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
16856bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1686f26d0771SStefano Zampini   }
16879c0b00dbSStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1688b4319ba4SBarry Smith   PetscFunctionReturn(0);
1689b4319ba4SBarry Smith }
1690b4319ba4SBarry Smith 
16912e74eeadSLisandro Dalcin #undef __FUNCT__
16922e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
1693a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
16942e74eeadSLisandro Dalcin {
16952e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
16962e74eeadSLisandro Dalcin   PetscErrorCode ierr;
169797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
169897563a80SStefano Zampini   PetscInt       i,zm,zn;
169997563a80SStefano Zampini #endif
1700f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
17012e74eeadSLisandro Dalcin 
17022e74eeadSLisandro Dalcin   PetscFunctionBegin;
17032e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1704f26d0771SStefano 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);
170597563a80SStefano Zampini   /* count negative indices */
170697563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
170797563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
17082e74eeadSLisandro Dalcin #endif
170997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
171097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
171197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
171297563a80SStefano Zampini   /* count negative indices (should be the same as before) */
171397563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
171497563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
171597563a80SStefano 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");
171697563a80SStefano 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");
171797563a80SStefano Zampini #endif
17182e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
17192e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
17202e74eeadSLisandro Dalcin }
17212e74eeadSLisandro Dalcin 
1722b4319ba4SBarry Smith #undef __FUNCT__
172397563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS"
1724a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
172597563a80SStefano Zampini {
172697563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
172797563a80SStefano Zampini   PetscErrorCode ierr;
172897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
172997563a80SStefano Zampini   PetscInt       i,zm,zn;
173097563a80SStefano Zampini #endif
1731f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
173297563a80SStefano Zampini 
173397563a80SStefano Zampini   PetscFunctionBegin;
173497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1735f26d0771SStefano 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);
173697563a80SStefano Zampini   /* count negative indices */
173797563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
173897563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
173997563a80SStefano Zampini #endif
174097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
174197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
174297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
174397563a80SStefano Zampini   /* count negative indices (should be the same as before) */
174497563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
174597563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
174697563a80SStefano 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");
174797563a80SStefano 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");
174897563a80SStefano Zampini #endif
174997563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
175097563a80SStefano Zampini   PetscFunctionReturn(0);
175197563a80SStefano Zampini }
175297563a80SStefano Zampini 
175397563a80SStefano Zampini #undef __FUNCT__
1754b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
1755a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1756b4319ba4SBarry Smith {
1757dfbe8321SBarry Smith   PetscErrorCode ierr;
1758b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1759b4319ba4SBarry Smith 
1760b4319ba4SBarry Smith   PetscFunctionBegin;
1761b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1762b4319ba4SBarry Smith   PetscFunctionReturn(0);
1763b4319ba4SBarry Smith }
1764b4319ba4SBarry Smith 
1765b4319ba4SBarry Smith #undef __FUNCT__
1766f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
1767a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1768f0006bf2SLisandro Dalcin {
1769f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1770f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1771f0006bf2SLisandro Dalcin 
1772f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1773f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1774f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1775f0006bf2SLisandro Dalcin }
1776f0006bf2SLisandro Dalcin 
1777f0006bf2SLisandro Dalcin #undef __FUNCT__
1778f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private"
1779f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
17802e74eeadSLisandro Dalcin {
1781f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
17822e74eeadSLisandro Dalcin   PetscErrorCode ierr;
17832e74eeadSLisandro Dalcin 
17842e74eeadSLisandro Dalcin   PetscFunctionBegin;
1785f0ae7da4SStefano Zampini   if (!n) {
1786f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1787f0ae7da4SStefano Zampini   } else {
1788f0ae7da4SStefano Zampini     PetscInt i;
1789f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1790f0ae7da4SStefano Zampini 
1791f0ae7da4SStefano Zampini     if (columns) {
1792f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1793f0ae7da4SStefano Zampini     } else {
1794f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
17952e74eeadSLisandro Dalcin     }
1796f0ae7da4SStefano Zampini     if (diag != 0.) {
1797f0ae7da4SStefano Zampini       const PetscScalar *array;
1798f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1799f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1800f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1801f0ae7da4SStefano Zampini       }
1802f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1803f0ae7da4SStefano Zampini     }
1804f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1805f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1806f0ae7da4SStefano Zampini   }
18072e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18082e74eeadSLisandro Dalcin }
18092e74eeadSLisandro Dalcin 
18102e74eeadSLisandro Dalcin #undef __FUNCT__
1811f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS"
1812f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
1813b4319ba4SBarry Smith {
18146e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
18156e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
18166e520ac8SStefano Zampini   PetscInt       *lrows;
1817dfbe8321SBarry Smith   PetscErrorCode ierr;
1818b4319ba4SBarry Smith 
1819b4319ba4SBarry Smith   PetscFunctionBegin;
1820f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1821f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1822f0ae7da4SStefano Zampini     PetscBool cong;
1823f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1824f0ae7da4SStefano 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");
1825f0ae7da4SStefano 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");
1826f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1827b4319ba4SBarry Smith   }
1828f0ae7da4SStefano Zampini #endif
18296e520ac8SStefano Zampini   /* get locally owned rows */
1830f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
18316e520ac8SStefano Zampini   /* fix right hand side if needed */
18326e520ac8SStefano Zampini   if (x && b) {
18336e520ac8SStefano Zampini     const PetscScalar *xx;
18346e520ac8SStefano Zampini     PetscScalar       *bb;
18352205254eSKarl Rupp 
18366e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
18376e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
18386e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
18396e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
18406e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
1841b4319ba4SBarry Smith   }
18426e520ac8SStefano Zampini   /* get rows associated to the local matrices */
18433d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
18446e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
18456e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
18466e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
18476e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
18486e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
18496e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18506e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
18516e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
18526e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1853f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
18546e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
1855b4319ba4SBarry Smith   PetscFunctionReturn(0);
1856b4319ba4SBarry Smith }
1857b4319ba4SBarry Smith 
1858b4319ba4SBarry Smith #undef __FUNCT__
1859f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS"
1860f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1861b4319ba4SBarry Smith {
1862b4319ba4SBarry Smith   PetscErrorCode ierr;
1863b4319ba4SBarry Smith 
1864b4319ba4SBarry Smith   PetscFunctionBegin;
1865f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1866f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1867f0ae7da4SStefano Zampini }
1868b4319ba4SBarry Smith 
1869f0ae7da4SStefano Zampini #undef __FUNCT__
1870f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS"
1871f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1872f0ae7da4SStefano Zampini {
1873f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1874f0ae7da4SStefano Zampini 
1875f0ae7da4SStefano Zampini   PetscFunctionBegin;
1876f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1877b4319ba4SBarry Smith   PetscFunctionReturn(0);
1878b4319ba4SBarry Smith }
1879b4319ba4SBarry Smith 
1880b4319ba4SBarry Smith #undef __FUNCT__
1881b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
1882a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1883b4319ba4SBarry Smith {
1884b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1885dfbe8321SBarry Smith   PetscErrorCode ierr;
1886b4319ba4SBarry Smith 
1887b4319ba4SBarry Smith   PetscFunctionBegin;
1888b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1889b4319ba4SBarry Smith   PetscFunctionReturn(0);
1890b4319ba4SBarry Smith }
1891b4319ba4SBarry Smith 
1892b4319ba4SBarry Smith #undef __FUNCT__
1893b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
1894a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1895b4319ba4SBarry Smith {
1896b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1897dfbe8321SBarry Smith   PetscErrorCode ierr;
1898b4319ba4SBarry Smith 
1899b4319ba4SBarry Smith   PetscFunctionBegin;
1900b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1901b4319ba4SBarry Smith   PetscFunctionReturn(0);
1902b4319ba4SBarry Smith }
1903b4319ba4SBarry Smith 
1904b4319ba4SBarry Smith #undef __FUNCT__
1905b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
1906a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1907b4319ba4SBarry Smith {
1908b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1909b4319ba4SBarry Smith 
1910b4319ba4SBarry Smith   PetscFunctionBegin;
1911b4319ba4SBarry Smith   *local = is->A;
1912b4319ba4SBarry Smith   PetscFunctionReturn(0);
1913b4319ba4SBarry Smith }
1914b4319ba4SBarry Smith 
1915b4319ba4SBarry Smith #undef __FUNCT__
1916b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
1917b4319ba4SBarry Smith /*@
1918b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1919b4319ba4SBarry Smith 
1920b4319ba4SBarry Smith   Input Parameter:
1921b4319ba4SBarry Smith .  mat - the matrix
1922b4319ba4SBarry Smith 
1923b4319ba4SBarry Smith   Output Parameter:
1924eb82efa4SStefano Zampini .  local - the local matrix
1925b4319ba4SBarry Smith 
1926b4319ba4SBarry Smith   Level: advanced
1927b4319ba4SBarry Smith 
1928b4319ba4SBarry Smith   Notes:
1929b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1930b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1931b4319ba4SBarry Smith   of the MatSetValues() operation.
1932b4319ba4SBarry Smith 
1933b4319ba4SBarry Smith .seealso: MATIS
1934b4319ba4SBarry Smith @*/
19357087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1936b4319ba4SBarry Smith {
19374ac538c5SBarry Smith   PetscErrorCode ierr;
1938b4319ba4SBarry Smith 
1939b4319ba4SBarry Smith   PetscFunctionBegin;
19400700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1941b4319ba4SBarry Smith   PetscValidPointer(local,2);
19424ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1943b4319ba4SBarry Smith   PetscFunctionReturn(0);
1944b4319ba4SBarry Smith }
1945b4319ba4SBarry Smith 
19463b03a366Sstefano_zampini #undef __FUNCT__
19473b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
1948a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
19493b03a366Sstefano_zampini {
19503b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
19513b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
19523b03a366Sstefano_zampini   PetscErrorCode ierr;
19533b03a366Sstefano_zampini 
19543b03a366Sstefano_zampini   PetscFunctionBegin;
19554e4c7dbeSStefano Zampini   if (is->A) {
19563b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
19573b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1958f0ae7da4SStefano 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);
19594e4c7dbeSStefano Zampini   }
19603b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
19613b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
19623b03a366Sstefano_zampini   is->A = local;
19633b03a366Sstefano_zampini   PetscFunctionReturn(0);
19643b03a366Sstefano_zampini }
19653b03a366Sstefano_zampini 
19663b03a366Sstefano_zampini #undef __FUNCT__
19673b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
19683b03a366Sstefano_zampini /*@
1969eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
19703b03a366Sstefano_zampini 
19713b03a366Sstefano_zampini   Input Parameter:
19723b03a366Sstefano_zampini .  mat - the matrix
1973eb82efa4SStefano Zampini .  local - the local matrix
19743b03a366Sstefano_zampini 
19753b03a366Sstefano_zampini   Output Parameter:
19763b03a366Sstefano_zampini 
19773b03a366Sstefano_zampini   Level: advanced
19783b03a366Sstefano_zampini 
19793b03a366Sstefano_zampini   Notes:
19803b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
19813b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
19823b03a366Sstefano_zampini 
19833b03a366Sstefano_zampini .seealso: MATIS
19843b03a366Sstefano_zampini @*/
19853b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
19863b03a366Sstefano_zampini {
19873b03a366Sstefano_zampini   PetscErrorCode ierr;
19883b03a366Sstefano_zampini 
19893b03a366Sstefano_zampini   PetscFunctionBegin;
19903b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1991b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
19923b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
19933b03a366Sstefano_zampini   PetscFunctionReturn(0);
19943b03a366Sstefano_zampini }
19953b03a366Sstefano_zampini 
19966726f965SBarry Smith #undef __FUNCT__
19976726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
1998a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
19996726f965SBarry Smith {
20006726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
20016726f965SBarry Smith   PetscErrorCode ierr;
20026726f965SBarry Smith 
20036726f965SBarry Smith   PetscFunctionBegin;
20046726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
20056726f965SBarry Smith   PetscFunctionReturn(0);
20066726f965SBarry Smith }
20076726f965SBarry Smith 
20086726f965SBarry Smith #undef __FUNCT__
20092e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
2010a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
20112e74eeadSLisandro Dalcin {
20122e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20132e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20142e74eeadSLisandro Dalcin 
20152e74eeadSLisandro Dalcin   PetscFunctionBegin;
20162e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
20172e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20182e74eeadSLisandro Dalcin }
20192e74eeadSLisandro Dalcin 
20202e74eeadSLisandro Dalcin #undef __FUNCT__
20212e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
2022a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
20232e74eeadSLisandro Dalcin {
20242e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
20252e74eeadSLisandro Dalcin   PetscErrorCode ierr;
20262e74eeadSLisandro Dalcin 
20272e74eeadSLisandro Dalcin   PetscFunctionBegin;
20282e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
2029e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
20302e74eeadSLisandro Dalcin 
20312e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
20322e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
2033e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2034e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20352e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20362e74eeadSLisandro Dalcin }
20372e74eeadSLisandro Dalcin 
20382e74eeadSLisandro Dalcin #undef __FUNCT__
20396726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
2040a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
20416726f965SBarry Smith {
20426726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
20436726f965SBarry Smith   PetscErrorCode ierr;
20446726f965SBarry Smith 
20456726f965SBarry Smith   PetscFunctionBegin;
20464e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
20476726f965SBarry Smith   PetscFunctionReturn(0);
20486726f965SBarry Smith }
20496726f965SBarry Smith 
2050284134d9SBarry Smith #undef __FUNCT__
2051f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS"
2052f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
2053f26d0771SStefano Zampini {
2054f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
2055f26d0771SStefano Zampini   Mat_IS         *x;
2056f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2057f26d0771SStefano Zampini   PetscBool      ismatis;
2058f26d0771SStefano Zampini #endif
2059f26d0771SStefano Zampini   PetscErrorCode ierr;
2060f26d0771SStefano Zampini 
2061f26d0771SStefano Zampini   PetscFunctionBegin;
2062f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2063f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
2064f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
2065f26d0771SStefano Zampini #endif
2066f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
2067f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
2068f26d0771SStefano Zampini   PetscFunctionReturn(0);
2069f26d0771SStefano Zampini }
2070f26d0771SStefano Zampini 
2071f26d0771SStefano Zampini #undef __FUNCT__
2072f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS"
2073f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
2074f26d0771SStefano Zampini {
2075f26d0771SStefano Zampini   Mat                    lA;
2076f26d0771SStefano Zampini   Mat_IS                 *matis;
2077f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2078f26d0771SStefano Zampini   IS                     is;
2079f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
2080f26d0771SStefano Zampini   PetscInt               nrg;
2081f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
2082f26d0771SStefano Zampini   PetscErrorCode         ierr;
2083f26d0771SStefano Zampini 
2084f26d0771SStefano Zampini   PetscFunctionBegin;
2085f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2086f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
2087f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
2088f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
2089f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2090f0ae7da4SStefano 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);
2091f26d0771SStefano Zampini #endif
2092f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
2093f26d0771SStefano Zampini   /* map from [0,nrl) to row */
2094f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
2095f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2096f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
2097f26d0771SStefano Zampini #else
2098f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
2099f26d0771SStefano Zampini #endif
2100f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
2101f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2102f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2103f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2104f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
2105f26d0771SStefano Zampini   /* compute new l2g map for columns */
2106f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2107f26d0771SStefano Zampini     const PetscInt *cg,*cl;
2108f26d0771SStefano Zampini     PetscInt       ncg;
2109f26d0771SStefano Zampini     PetscInt       ncl;
2110f26d0771SStefano Zampini 
2111f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2112f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2113f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2114f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2115f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2116f0ae7da4SStefano 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);
2117f26d0771SStefano Zampini #endif
2118f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2119f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2120f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2121f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2122f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2123f26d0771SStefano Zampini #else
2124f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2125f26d0771SStefano Zampini #endif
2126f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2127f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2128f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2129f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2130f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2131f26d0771SStefano Zampini   } else {
2132f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2133f26d0771SStefano Zampini     cl2g = rl2g;
2134f26d0771SStefano Zampini   }
2135f26d0771SStefano Zampini   /* create the MATIS submatrix */
2136f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2137f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2138f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2139f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2140b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2141f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2142f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2143f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2144f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2145f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2146f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2147f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2148f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2149f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2150f26d0771SStefano Zampini   /* remove unsupported ops */
2151f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2152f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2153f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2154f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2155f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2156f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2157f26d0771SStefano Zampini   PetscFunctionReturn(0);
2158f26d0771SStefano Zampini }
2159f26d0771SStefano Zampini 
2160f26d0771SStefano Zampini #undef __FUNCT__
2161284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
2162284134d9SBarry Smith /*@
21633c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2164284134d9SBarry Smith        process but not across processes.
2165284134d9SBarry Smith 
2166284134d9SBarry Smith    Input Parameters:
2167284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2168e176bc59SStefano Zampini .     bs      - block size of the matrix
2169df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2170e176bc59SStefano Zampini .     rmap    - local to global map for rows
2171e176bc59SStefano Zampini -     cmap    - local to global map for cols
2172284134d9SBarry Smith 
2173284134d9SBarry Smith    Output Parameter:
2174284134d9SBarry Smith .    A - the resulting matrix
2175284134d9SBarry Smith 
21768e6c10adSSatish Balay    Level: advanced
21778e6c10adSSatish Balay 
21783c212e90SHong Zhang    Notes: See MATIS for more details.
21796fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
21806fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
21813c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2182284134d9SBarry Smith 
2183284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2184284134d9SBarry Smith @*/
2185e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2186284134d9SBarry Smith {
2187284134d9SBarry Smith   PetscErrorCode ierr;
2188284134d9SBarry Smith 
2189284134d9SBarry Smith   PetscFunctionBegin;
21906fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2191284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
21926fdf41d1SStefano Zampini   if (bs > 0) {
2193d3ee2243SStefano Zampini     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
21946fdf41d1SStefano Zampini   }
2195284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
2196284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2197e176bc59SStefano Zampini   if (rmap && cmap) {
2198e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2199e176bc59SStefano Zampini   } else if (!rmap) {
2200e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2201e176bc59SStefano Zampini   } else {
2202e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2203e176bc59SStefano Zampini   }
2204284134d9SBarry Smith   PetscFunctionReturn(0);
2205284134d9SBarry Smith }
2206284134d9SBarry Smith 
2207b4319ba4SBarry Smith /*MC
2208f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2209b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2210b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2211b4319ba4SBarry Smith    product is handled "implicitly".
2212b4319ba4SBarry Smith 
2213b4319ba4SBarry Smith    Operations Provided:
22146726f965SBarry Smith +  MatMult()
22152e74eeadSLisandro Dalcin .  MatMultAdd()
22162e74eeadSLisandro Dalcin .  MatMultTranspose()
22172e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
22186726f965SBarry Smith .  MatZeroEntries()
22196726f965SBarry Smith .  MatSetOption()
22202e74eeadSLisandro Dalcin .  MatZeroRows()
22212e74eeadSLisandro Dalcin .  MatSetValues()
222297563a80SStefano Zampini .  MatSetValuesBlocked()
22236726f965SBarry Smith .  MatSetValuesLocal()
222497563a80SStefano Zampini .  MatSetValuesBlockedLocal()
22252e74eeadSLisandro Dalcin .  MatScale()
22262e74eeadSLisandro Dalcin .  MatGetDiagonal()
22272b404112SStefano Zampini .  MatMissingDiagonal()
22282b404112SStefano Zampini .  MatDuplicate()
22292b404112SStefano Zampini .  MatCopy()
2230f26d0771SStefano Zampini .  MatAXPY()
2231f26d0771SStefano Zampini .  MatGetSubMatrix()
2232f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2233d7f69cd0SStefano Zampini .  MatTranspose()
22346726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2235b4319ba4SBarry Smith 
2236b4319ba4SBarry Smith    Options Database Keys:
2237b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2238b4319ba4SBarry Smith 
2239b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
2240b4319ba4SBarry Smith 
2241b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2242b4319ba4SBarry Smith 
2243b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2244eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2245b4319ba4SBarry Smith 
2246b4319ba4SBarry Smith   Level: advanced
2247b4319ba4SBarry Smith 
2248f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2249b4319ba4SBarry Smith 
2250b4319ba4SBarry Smith M*/
2251b4319ba4SBarry Smith 
2252b4319ba4SBarry Smith #undef __FUNCT__
2253b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
22548cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2255b4319ba4SBarry Smith {
2256dfbe8321SBarry Smith   PetscErrorCode ierr;
2257b4319ba4SBarry Smith   Mat_IS         *b;
2258b4319ba4SBarry Smith 
2259b4319ba4SBarry Smith   PetscFunctionBegin;
2260b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2261b4319ba4SBarry Smith   A->data = (void*)b;
2262b4319ba4SBarry Smith 
2263e176bc59SStefano Zampini   /* matrix ops */
2264e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2265b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
22662e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
22672e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
22682e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2269b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2270b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
22712e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
227298921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2273b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2274f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
22752e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2276f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2277b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2278b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2279b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
22806726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
22812e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
22822e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
22836726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
228469796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
228569796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
228645471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2287ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
22886bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
22892b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2290659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
2291a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
2292f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
22933fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
22943fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2295d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
22967fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
2297*ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
2298b4319ba4SBarry Smith 
2299b7ce53b6SStefano Zampini   /* special MATIS functions */
2300bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
2301bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2302b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
23032e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2304cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
230517667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2306b4319ba4SBarry Smith   PetscFunctionReturn(0);
2307b4319ba4SBarry Smith }
2308