xref: /petsc/src/mat/impls/is/matis.c (revision acdf38a77457c3114c42bf1d14c27617c1202ada)
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__
449d7f69cd0SStefano Zampini #define __FUNCT__ "MatTranspose_IS"
450d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
451d7f69cd0SStefano Zampini {
452d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
453d7f69cd0SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
454d7f69cd0SStefano Zampini   PetscBool              notset = PETSC_FALSE,cong = PETSC_TRUE;
455d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
456d7f69cd0SStefano Zampini 
457d7f69cd0SStefano Zampini   PetscFunctionBegin;
458d7f69cd0SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
459d7f69cd0SStefano Zampini     PetscBool rcong,ccong;
460d7f69cd0SStefano Zampini 
461d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->cmap,A->rmap,&rcong);CHKERRQ(ierr);
462d7f69cd0SStefano Zampini     ierr = PetscLayoutCompare((*B)->rmap,A->cmap,&ccong);CHKERRQ(ierr);
463fa520230SStefano Zampini     cong = (PetscBool)(rcong || ccong);
464d7f69cd0SStefano Zampini   }
465d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B == A || !cong) {
466d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
467d7f69cd0SStefano Zampini   } else {
468d7f69cd0SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATIS,&notset);CHKERRQ(ierr);
469d7f69cd0SStefano Zampini     C = *B;
470d7f69cd0SStefano Zampini   }
471d7f69cd0SStefano Zampini 
472d7f69cd0SStefano Zampini   if (!notset) {
473d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
474d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
475d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
476d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
477d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
478d7f69cd0SStefano Zampini   }
479d7f69cd0SStefano Zampini 
480d7f69cd0SStefano Zampini   /* perform local transposition */
481d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
482d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
483d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
484d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
485d7f69cd0SStefano Zampini 
486d7f69cd0SStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
487d7f69cd0SStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
488d7f69cd0SStefano Zampini 
489d7f69cd0SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
490d7f69cd0SStefano Zampini     if (!cong) {
491d7f69cd0SStefano Zampini       ierr = MatDestroy(B);CHKERRQ(ierr);
492d7f69cd0SStefano Zampini     }
493d7f69cd0SStefano Zampini     *B = C;
494d7f69cd0SStefano Zampini   } else {
495d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
496d7f69cd0SStefano Zampini   }
497d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
498d7f69cd0SStefano Zampini }
499d7f69cd0SStefano Zampini 
500d7f69cd0SStefano Zampini #undef __FUNCT__
5013fd1c9e7SStefano Zampini #define __FUNCT__ "MatDiagonalSet_IS"
5023fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
5033fd1c9e7SStefano Zampini {
5043fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
5053fd1c9e7SStefano Zampini   PetscErrorCode ierr;
5063fd1c9e7SStefano Zampini 
5073fd1c9e7SStefano Zampini   PetscFunctionBegin;
5083fd1c9e7SStefano Zampini   if (!D) { /* this code branch is used by MatShift_IS */
5093fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
5103fd1c9e7SStefano Zampini   } else {
5113fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5123fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5133fd1c9e7SStefano Zampini   }
5143fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
5153fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
5163fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
5173fd1c9e7SStefano Zampini }
5183fd1c9e7SStefano Zampini 
5193fd1c9e7SStefano Zampini #undef __FUNCT__
5203fd1c9e7SStefano Zampini #define __FUNCT__ "MatShift_IS"
5213fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
5223fd1c9e7SStefano Zampini {
5233fd1c9e7SStefano Zampini   PetscErrorCode ierr;
5243fd1c9e7SStefano Zampini 
5253fd1c9e7SStefano Zampini   PetscFunctionBegin;
5263fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
5273fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
5283fd1c9e7SStefano Zampini }
5293fd1c9e7SStefano Zampini 
5303fd1c9e7SStefano Zampini #undef __FUNCT__
531f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesLocal_SubMat_IS"
532f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
533f26d0771SStefano Zampini {
534f26d0771SStefano Zampini   PetscErrorCode ierr;
535f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
536f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
537f26d0771SStefano Zampini 
538f26d0771SStefano Zampini   PetscFunctionBegin;
539f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
540f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
541f26d0771SStefano Zampini #endif
542f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
543f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
544f26d0771SStefano Zampini   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
545f26d0771SStefano Zampini   PetscFunctionReturn(0);
546f26d0771SStefano Zampini }
547f26d0771SStefano Zampini 
548f26d0771SStefano Zampini #undef __FUNCT__
549f26d0771SStefano Zampini #define __FUNCT__ "MatSetValuesBlockedLocal_SubMat_IS"
550f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
551f26d0771SStefano Zampini {
552f26d0771SStefano Zampini   PetscErrorCode ierr;
553f26d0771SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
554f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
555f26d0771SStefano Zampini 
556f26d0771SStefano Zampini   PetscFunctionBegin;
557f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
558f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
559f26d0771SStefano Zampini #endif
560f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
561f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
562f26d0771SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
563f26d0771SStefano Zampini   PetscFunctionReturn(0);
564f26d0771SStefano Zampini }
565f26d0771SStefano Zampini 
566f26d0771SStefano Zampini #undef __FUNCT__
567a8116848SStefano Zampini #define __FUNCT__ "PetscLayoutMapLocal_Private"
568f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
569a8116848SStefano Zampini {
570a8116848SStefano Zampini   PetscInt      *owners = map->range;
571a8116848SStefano Zampini   PetscInt       n      = map->n;
572a8116848SStefano Zampini   PetscSF        sf;
573a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
574a8116848SStefano Zampini   PetscSFNode   *ridxs;
575a8116848SStefano Zampini   PetscMPIInt    rank;
576a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
577a8116848SStefano Zampini   PetscErrorCode ierr;
578a8116848SStefano Zampini 
579a8116848SStefano Zampini   PetscFunctionBegin;
580a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
581a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
582a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
583a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
584a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
585a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
586a8116848SStefano Zampini     const PetscInt idx = idxs[r];
587a8116848SStefano Zampini     if (idx < 0 || map->N <= idx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index %D out of range [0,%D)",idx,map->N);
588a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
589a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
590a8116848SStefano Zampini     }
591a8116848SStefano Zampini     ridxs[r].rank = p;
592a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
593a8116848SStefano Zampini   }
594a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
595a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
596a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
597a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
598f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
599a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
600f0ae7da4SStefano Zampini 
601f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
602a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
603a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
604a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
605a8116848SStefano Zampini     start -= cum;
606a8116848SStefano Zampini     cum = 0;
607a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
608a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
609a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
610a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
611a8116848SStefano Zampini   }
612a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
613a8116848SStefano Zampini   /* Compress and put in indices */
614a8116848SStefano Zampini   for (r = 0; r < n; ++r)
615a8116848SStefano Zampini     if (lidxs[r] >= 0) {
616a8116848SStefano Zampini       if (work) work[len] = work[r];
617a8116848SStefano Zampini       lidxs[len++] = r;
618a8116848SStefano Zampini     }
619a8116848SStefano Zampini   if (on) *on = len;
620a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
621a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
622a8116848SStefano Zampini   PetscFunctionReturn(0);
623a8116848SStefano Zampini }
624a8116848SStefano Zampini 
625a8116848SStefano Zampini #undef __FUNCT__
626a8116848SStefano Zampini #define __FUNCT__ "MatGetSubMatrix_IS"
627a8116848SStefano Zampini static PetscErrorCode MatGetSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
628a8116848SStefano Zampini {
629a8116848SStefano Zampini   Mat               locmat,newlocmat;
630a8116848SStefano Zampini   Mat_IS            *newmatis;
631a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
632a8116848SStefano Zampini   Vec               rtest,ltest;
633a8116848SStefano Zampini   const PetscScalar *array;
634a8116848SStefano Zampini #endif
635a8116848SStefano Zampini   const PetscInt    *idxs;
636a8116848SStefano Zampini   PetscInt          i,m,n;
637a8116848SStefano Zampini   PetscErrorCode    ierr;
638a8116848SStefano Zampini 
639a8116848SStefano Zampini   PetscFunctionBegin;
640a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
641a8116848SStefano Zampini     PetscBool ismatis;
642a8116848SStefano Zampini 
643a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
644a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
645a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
646a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
647a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
648a8116848SStefano Zampini   }
649a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
650a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
651a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
652a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
653a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
654a8116848SStefano Zampini   for (i=0;i<n;i++) {
655a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
656a8116848SStefano Zampini   }
657a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
658a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
659a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
660a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
661a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
662fd479f66SMatthew G. Knepley   for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Irow may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
663a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
664a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
665a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
666a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
667a8116848SStefano Zampini   for (i=0;i<n;i++) {
668a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
669a8116848SStefano Zampini   }
670a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
671a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
672a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
673a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
674a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
675fd479f66SMatthew G. Knepley   for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Icol may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
676a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
677a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
678a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
679a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
680a8116848SStefano Zampini #endif
681a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
682a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
683a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
684a8116848SStefano Zampini     IS                     is;
685a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
6866dd40735SStefano Zampini     PetscInt               ll,newloc;
687a8116848SStefano Zampini     MPI_Comm               comm;
688a8116848SStefano Zampini 
689a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
690a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
691a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
692a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
693a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
694a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
695a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
696a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
697f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
698a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
6993d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
7003d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
701a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
702a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
703a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
704a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
705a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
7063d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
707a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
708a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
7093d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
710a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
711a8116848SStefano Zampini         lidxs[newloc] = i;
712a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
713a8116848SStefano Zampini       }
714a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
715a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
716a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
717a8116848SStefano Zampini     /* local is to extract local submatrix */
718a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
719a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
720a8116848SStefano Zampini     if (mat->congruentlayouts == -1) { /* first time we compare rows and cols layouts */
721a8116848SStefano Zampini       PetscBool cong;
722a8116848SStefano Zampini       ierr = PetscLayoutCompare(mat->rmap,mat->cmap,&cong);CHKERRQ(ierr);
723a8116848SStefano Zampini       if (cong) mat->congruentlayouts = 1;
724a8116848SStefano Zampini       else      mat->congruentlayouts = 0;
725a8116848SStefano Zampini     }
726a8116848SStefano Zampini     if (mat->congruentlayouts && irow == icol) {
727a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
728a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
729a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
730a8116848SStefano Zampini     } else {
731a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
732a8116848SStefano Zampini 
733a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
734a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
735f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
736a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
7373d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
738a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
739a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
740a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
741a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
742a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
7433d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
744a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
745a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
7463d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
747a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
748a8116848SStefano Zampini           lidxs[newloc] = i;
749a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
750a8116848SStefano Zampini         }
751a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
752a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
753a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
754a8116848SStefano Zampini       /* local is to extract local submatrix */
755a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
756a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
757a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
758a8116848SStefano Zampini     }
759a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
760a8116848SStefano Zampini   } else {
761a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
762a8116848SStefano Zampini   }
763a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
764a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
765a8116848SStefano Zampini   ierr = MatGetSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
766a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
767a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
768a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
769a8116848SStefano Zampini   }
770a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
771a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
772a8116848SStefano Zampini   PetscFunctionReturn(0);
773a8116848SStefano Zampini }
774a8116848SStefano Zampini 
775a8116848SStefano Zampini #undef __FUNCT__
7762b404112SStefano Zampini #define __FUNCT__ "MatCopy_IS"
777a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
7782b404112SStefano Zampini {
7792b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
7802b404112SStefano Zampini   PetscBool      ismatis;
7812b404112SStefano Zampini   PetscErrorCode ierr;
7822b404112SStefano Zampini 
7832b404112SStefano Zampini   PetscFunctionBegin;
7842b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
7852b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
7862b404112SStefano Zampini   b = (Mat_IS*)B->data;
7872b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
7882b404112SStefano Zampini   PetscFunctionReturn(0);
7892b404112SStefano Zampini }
7902b404112SStefano Zampini 
7912b404112SStefano Zampini #undef __FUNCT__
7926bd84002SStefano Zampini #define __FUNCT__ "MatMissingDiagonal_IS"
793a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
7946bd84002SStefano Zampini {
795527b2640SStefano Zampini   Vec               v;
796527b2640SStefano Zampini   const PetscScalar *array;
797527b2640SStefano Zampini   PetscInt          i,n;
7986bd84002SStefano Zampini   PetscErrorCode    ierr;
7996bd84002SStefano Zampini 
8006bd84002SStefano Zampini   PetscFunctionBegin;
801527b2640SStefano Zampini   *missing = PETSC_FALSE;
802527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
803527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
804527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
805527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
806527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
807527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
808527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
809527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
810527b2640SStefano Zampini   if (d) {
811527b2640SStefano Zampini     *d = -1;
812527b2640SStefano Zampini     if (*missing) {
813527b2640SStefano Zampini       PetscInt rstart;
814527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
815527b2640SStefano Zampini       *d = i+rstart;
816527b2640SStefano Zampini     }
817527b2640SStefano Zampini   }
8186bd84002SStefano Zampini   PetscFunctionReturn(0);
8196bd84002SStefano Zampini }
8206bd84002SStefano Zampini 
8216bd84002SStefano Zampini #undef __FUNCT__
822cf0a3239SStefano Zampini #define __FUNCT__ "MatISSetUpSF_IS"
823cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
82428f4e0baSStefano Zampini {
82528f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
82628f4e0baSStefano Zampini   const PetscInt *gidxs;
8274f2d7cafSStefano Zampini   PetscInt       nleaves;
82828f4e0baSStefano Zampini   PetscErrorCode ierr;
82928f4e0baSStefano Zampini 
83028f4e0baSStefano Zampini   PetscFunctionBegin;
8314f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
83228f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
8333bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
8344f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
8354f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
8363bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
8374f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
838a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
8393d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
840a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
841a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
8423d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
843a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
8443d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
845a8116848SStefano Zampini   } else {
846a8116848SStefano Zampini     matis->csf = matis->sf;
847a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
848a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
849a8116848SStefano Zampini   }
85028f4e0baSStefano Zampini   PetscFunctionReturn(0);
85128f4e0baSStefano Zampini }
8522e1947a5SStefano Zampini 
8532e1947a5SStefano Zampini #undef __FUNCT__
8542e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
855eb82efa4SStefano Zampini /*@
856a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
857a88811baSStefano Zampini 
858a88811baSStefano Zampini    Collective on MPI_Comm
859a88811baSStefano Zampini 
860a88811baSStefano Zampini    Input Parameters:
861a88811baSStefano Zampini +  B - the matrix
862a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
863a88811baSStefano Zampini            (same value is used for all local rows)
864a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
865a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
866a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
867a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
868a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
869a88811baSStefano Zampini            the diagonal entry even if it is zero.
870a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
871a88811baSStefano Zampini            submatrix (same value is used for all local rows).
872a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
873a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
874a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
875a88811baSStefano Zampini            structure. The size of this array is equal to the number
876a88811baSStefano Zampini            of local rows, i.e 'm'.
877a88811baSStefano Zampini 
878a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
879a88811baSStefano Zampini 
880a88811baSStefano Zampini    Level: intermediate
881a88811baSStefano Zampini 
882a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
883a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
884a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
885a88811baSStefano Zampini 
886a88811baSStefano Zampini .keywords: matrix
887a88811baSStefano Zampini 
8883c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
889a88811baSStefano Zampini @*/
8902e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
8912e1947a5SStefano Zampini {
8922e1947a5SStefano Zampini   PetscErrorCode ierr;
8932e1947a5SStefano Zampini 
8942e1947a5SStefano Zampini   PetscFunctionBegin;
8952e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
8962e1947a5SStefano Zampini   PetscValidType(B,1);
8972e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
8982e1947a5SStefano Zampini   PetscFunctionReturn(0);
8992e1947a5SStefano Zampini }
9002e1947a5SStefano Zampini 
9012e1947a5SStefano Zampini #undef __FUNCT__
9022e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
9037230de76SStefano Zampini static PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
9042e1947a5SStefano Zampini {
9052e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
90628f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
9072e1947a5SStefano Zampini   PetscErrorCode ierr;
9082e1947a5SStefano Zampini 
9092e1947a5SStefano Zampini   PetscFunctionBegin;
9106c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
911cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
9124f2d7cafSStefano Zampini 
9134f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
9144f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
9154f2d7cafSStefano Zampini 
9164f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
9174f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
9184f2d7cafSStefano Zampini 
91928f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
92028f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
92128f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
92228f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
9234f2d7cafSStefano Zampini 
9244f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
92528f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
9264f2d7cafSStefano Zampini 
9274f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
92828f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
9294f2d7cafSStefano Zampini 
9304f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
93128f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
9322e1947a5SStefano Zampini   PetscFunctionReturn(0);
9332e1947a5SStefano Zampini }
934b4319ba4SBarry Smith 
935b4319ba4SBarry Smith #undef __FUNCT__
9363927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
9373927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
9383927de2eSStefano Zampini {
9393927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
9403927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
941ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
9423927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
9433927de2eSStefano Zampini   PetscInt        lrows,lcols;
9443927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
9453927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
9463927de2eSStefano Zampini   PetscBool       isdense,issbaij;
9473927de2eSStefano Zampini   PetscErrorCode  ierr;
9483927de2eSStefano Zampini 
9493927de2eSStefano Zampini   PetscFunctionBegin;
9503927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
9513927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
9523927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
9533927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
9543927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
9553927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
956ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
957ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
9587230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
959ecf5a873SStefano Zampini   } else {
960ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
961ecf5a873SStefano Zampini   }
962ecf5a873SStefano Zampini 
9633927de2eSStefano Zampini   if (issbaij) {
9643927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
9653927de2eSStefano Zampini   }
9663927de2eSStefano Zampini   /*
967ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
9683927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
9693927de2eSStefano Zampini   */
970cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
9713927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
9723927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
9733927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
9743927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
9753927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
9763927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
9773927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
9783927de2eSStefano Zampini       row_ownership[j] = i;
9793927de2eSStefano Zampini     }
9803927de2eSStefano Zampini   }
9817230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
9823927de2eSStefano Zampini 
9833927de2eSStefano Zampini   /*
9843927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
9853927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
9863927de2eSStefano Zampini   */
9873927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
9883927de2eSStefano Zampini   /* preallocation as a MATAIJ */
9893927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
9903927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
991ecf5a873SStefano Zampini       PetscInt index_row = global_indices_r[i];
9923927de2eSStefano Zampini       for (j=i;j<local_rows;j++) {
9933927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
994ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
9953927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
9963927de2eSStefano Zampini           my_dnz[i] += 1;
9973927de2eSStefano Zampini         } else { /* offdiag block */
9983927de2eSStefano Zampini           my_onz[i] += 1;
9993927de2eSStefano Zampini         }
10003927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
10013927de2eSStefano Zampini         if (i != j) {
10023927de2eSStefano Zampini           owner = row_ownership[index_col];
10033927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
10043927de2eSStefano Zampini             my_dnz[j] += 1;
10053927de2eSStefano Zampini           } else {
10063927de2eSStefano Zampini             my_onz[j] += 1;
10073927de2eSStefano Zampini           }
10083927de2eSStefano Zampini         }
10093927de2eSStefano Zampini       }
10103927de2eSStefano Zampini     }
1011bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1012bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1013bb1015c3SStefano Zampini     PetscBool      done;
1014bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1015bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1016bb1015c3SStefano Zampini     jptr = jj;
1017bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1018bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1019bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1020bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1021bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1022bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1023bb1015c3SStefano Zampini           my_dnz[i] += 1;
1024bb1015c3SStefano Zampini         } else { /* offdiag block */
1025bb1015c3SStefano Zampini           my_onz[i] += 1;
1026bb1015c3SStefano Zampini         }
1027bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1028bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1029bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1030bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1031bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1032bb1015c3SStefano Zampini           } else {
1033bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1034bb1015c3SStefano Zampini           }
1035bb1015c3SStefano Zampini         }
1036bb1015c3SStefano Zampini       }
1037bb1015c3SStefano Zampini     }
1038bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1039bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1040bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
10413927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
10423927de2eSStefano Zampini       const PetscInt *cols;
1043ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
10443927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
10453927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
10463927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1047ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
10483927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
10493927de2eSStefano Zampini           my_dnz[i] += 1;
10503927de2eSStefano Zampini         } else { /* offdiag block */
10513927de2eSStefano Zampini           my_onz[i] += 1;
10523927de2eSStefano Zampini         }
10533927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1054d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
10553927de2eSStefano Zampini           owner = row_ownership[index_col];
10563927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1057d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
10583927de2eSStefano Zampini           } else {
1059d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
10603927de2eSStefano Zampini           }
10613927de2eSStefano Zampini         }
10623927de2eSStefano Zampini       }
10633927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
10643927de2eSStefano Zampini     }
10653927de2eSStefano Zampini   }
1066ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1067ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
10687230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1069ecf5a873SStefano Zampini   }
10703927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1071ecf5a873SStefano Zampini 
1072ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
10733927de2eSStefano Zampini   if (maxreduce) {
10743927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
10753927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1076bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
10773927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
10783927de2eSStefano Zampini   } else {
10793927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
10803927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1081bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
10823927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
10833927de2eSStefano Zampini   }
10843927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
10853927de2eSStefano Zampini 
10863927de2eSStefano Zampini   /* Resize preallocation if overestimated */
10873927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
10883927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
10893927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
10903927de2eSStefano Zampini   }
10911670daf9Sstefano_zampini 
10921670daf9Sstefano_zampini   /* Set preallocation */
10933927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
10943927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
10953927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
10963927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
10973927de2eSStefano Zampini   }
10983927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
10993927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
11003927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
11013927de2eSStefano Zampini   if (issbaij) {
11023927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
11033927de2eSStefano Zampini   }
11043927de2eSStefano Zampini   PetscFunctionReturn(0);
11053927de2eSStefano Zampini }
11063927de2eSStefano Zampini 
11073927de2eSStefano Zampini #undef __FUNCT__
1108b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
11097230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1110b7ce53b6SStefano Zampini {
1111b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1112d9a9e74cSStefano Zampini   Mat            local_mat;
1113b7ce53b6SStefano Zampini   /* info on mat */
11143cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1115b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1116b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1117b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1118b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1119b9ed4604SStefano Zampini #endif
11207c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1121b7ce53b6SStefano Zampini   /* values insertion */
1122b7ce53b6SStefano Zampini   PetscScalar    *array;
1123b7ce53b6SStefano Zampini   /* work */
1124b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1125b7ce53b6SStefano Zampini 
1126b7ce53b6SStefano Zampini   PetscFunctionBegin;
1127b7ce53b6SStefano Zampini   /* get info from mat */
11287c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
11297c03b4e8SStefano Zampini   if (nsubdomains == 1) {
11301670daf9Sstefano_zampini     Mat            B;
11311670daf9Sstefano_zampini     IS             rows,cols;
1132*acdf38a7Sstefano_zampini     IS             irows,icols;
11331670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
11341670daf9Sstefano_zampini 
11351670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
11361670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
11371670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
11381670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
11391670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
11401670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1141*acdf38a7Sstefano_zampini     ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1142*acdf38a7Sstefano_zampini     ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1143*acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr);
1144*acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr);
1145*acdf38a7Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
1146*acdf38a7Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
1147*acdf38a7Sstefano_zampini     ierr = MatConvert(matis->A,MATAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
1148*acdf38a7Sstefano_zampini     ierr = MatGetSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1149*acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1150*acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1151*acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
11527c03b4e8SStefano Zampini     PetscFunctionReturn(0);
11537c03b4e8SStefano Zampini   }
1154b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1155b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
11563cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1157b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1158b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
1159686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1160b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1161b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1162b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1163b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1164b9ed4604SStefano Zampini   lb[0] = isseqdense;
1165b9ed4604SStefano Zampini   lb[1] = isseqaij;
1166b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1167b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1168b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1169b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1170b9ed4604SStefano Zampini #endif
1171b7ce53b6SStefano Zampini 
1172b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
11733927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
11743cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
11753927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
1176b9ed4604SStefano Zampini     if (!isseqsbaij) {
1177b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1178b9ed4604SStefano Zampini     } else {
1179b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1180b9ed4604SStefano Zampini     }
11813927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1182b7ce53b6SStefano Zampini   } else {
11833cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1184b7ce53b6SStefano Zampini     /* some checks */
1185b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1186b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
11873cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
11886c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
11896c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
11906c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
11916c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
11926c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1193b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1194b7ce53b6SStefano Zampini   }
1195d9a9e74cSStefano Zampini 
1196b9ed4604SStefano Zampini   if (isseqsbaij) {
1197d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1198d9a9e74cSStefano Zampini   } else {
1199d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1200d9a9e74cSStefano Zampini     local_mat = matis->A;
1201d9a9e74cSStefano Zampini   }
1202686e3a49SStefano Zampini 
1203b7ce53b6SStefano Zampini   /* Set values */
1204ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1205b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
1206ecf5a873SStefano Zampini     PetscInt i,*dummy_rows,*dummy_cols;
1207ecf5a873SStefano Zampini 
1208ecf5a873SStefano Zampini     if (local_rows != local_cols) {
1209ecf5a873SStefano Zampini       ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr);
1210ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1211ecf5a873SStefano Zampini       for (i=0;i<local_cols;i++) dummy_cols[i] = i;
1212ecf5a873SStefano Zampini     } else {
1213ecf5a873SStefano Zampini       ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr);
1214ecf5a873SStefano Zampini       for (i=0;i<local_rows;i++) dummy_rows[i] = i;
1215ecf5a873SStefano Zampini       dummy_cols = dummy_rows;
1216ecf5a873SStefano Zampini     }
1217b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1218d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
1219ecf5a873SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr);
1220d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
1221ecf5a873SStefano Zampini     if (dummy_rows != dummy_cols) {
1222ecf5a873SStefano Zampini       ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr);
1223ecf5a873SStefano Zampini     } else {
1224ecf5a873SStefano Zampini       ierr = PetscFree(dummy_rows);CHKERRQ(ierr);
1225ecf5a873SStefano Zampini     }
1226686e3a49SStefano Zampini   } else if (isseqaij) {
1227ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1228686e3a49SStefano Zampini     PetscBool done;
1229686e3a49SStefano Zampini 
1230d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1231bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ called from %s\n",__FUNCT__);
1232d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1233686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1234ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1235686e3a49SStefano Zampini     }
1236d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1237bb1015c3SStefano Zampini     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from %s\n",__FUNCT__);
1238d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1239686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1240ecf5a873SStefano Zampini     PetscInt i;
1241c0962df8SStefano Zampini 
1242686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1243686e3a49SStefano Zampini       PetscInt       j;
1244ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1245686e3a49SStefano Zampini 
1246ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1247ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1248ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1249686e3a49SStefano Zampini     }
1250b7ce53b6SStefano Zampini   }
1251b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1252d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1253b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1254b9ed4604SStefano Zampini   if (isseqdense) {
1255b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1256b7ce53b6SStefano Zampini   }
1257b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1258b7ce53b6SStefano Zampini }
1259b7ce53b6SStefano Zampini 
1260b7ce53b6SStefano Zampini #undef __FUNCT__
1261b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
1262b7ce53b6SStefano Zampini /*@
1263b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1264b7ce53b6SStefano Zampini 
1265b7ce53b6SStefano Zampini   Input Parameter:
1266b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1267b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1268b7ce53b6SStefano Zampini 
1269b7ce53b6SStefano Zampini   Output Parameter:
1270b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1271b7ce53b6SStefano Zampini 
1272b7ce53b6SStefano Zampini   Level: developer
1273b7ce53b6SStefano Zampini 
1274eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1275b7ce53b6SStefano Zampini 
1276b7ce53b6SStefano Zampini .seealso: MATIS
1277b7ce53b6SStefano Zampini @*/
1278b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1279b7ce53b6SStefano Zampini {
1280b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1281b7ce53b6SStefano Zampini 
1282b7ce53b6SStefano Zampini   PetscFunctionBegin;
1283b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1284b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1285b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1286b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1287b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1288b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
12896c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1290b7ce53b6SStefano Zampini   }
1291b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1292b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1293b7ce53b6SStefano Zampini }
1294b7ce53b6SStefano Zampini 
1295b7ce53b6SStefano Zampini #undef __FUNCT__
1296ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
1297ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1298ad6194a2SStefano Zampini {
1299ad6194a2SStefano Zampini   PetscErrorCode ierr;
1300ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1301ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1302ad6194a2SStefano Zampini   Mat            B,localmat;
1303ad6194a2SStefano Zampini 
1304ad6194a2SStefano Zampini   PetscFunctionBegin;
1305ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1306ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1307ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1308e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1309ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1310ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1311b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1312ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1313ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1314ad6194a2SStefano Zampini   *newmat = B;
1315ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1316ad6194a2SStefano Zampini }
1317ad6194a2SStefano Zampini 
1318ad6194a2SStefano Zampini #undef __FUNCT__
131969796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
1320a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
132169796d55SStefano Zampini {
132269796d55SStefano Zampini   PetscErrorCode ierr;
132369796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
132469796d55SStefano Zampini   PetscBool      local_sym;
132569796d55SStefano Zampini 
132669796d55SStefano Zampini   PetscFunctionBegin;
132769796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1328b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
132969796d55SStefano Zampini   PetscFunctionReturn(0);
133069796d55SStefano Zampini }
133169796d55SStefano Zampini 
133269796d55SStefano Zampini #undef __FUNCT__
133369796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
1334a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
133569796d55SStefano Zampini {
133669796d55SStefano Zampini   PetscErrorCode ierr;
133769796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
133869796d55SStefano Zampini   PetscBool      local_sym;
133969796d55SStefano Zampini 
134069796d55SStefano Zampini   PetscFunctionBegin;
134169796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1342b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
134369796d55SStefano Zampini   PetscFunctionReturn(0);
134469796d55SStefano Zampini }
134569796d55SStefano Zampini 
134669796d55SStefano Zampini #undef __FUNCT__
134745471136SStefano Zampini #define __FUNCT__ "MatIsStructurallySymmetric_IS"
134845471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
134945471136SStefano Zampini {
135045471136SStefano Zampini   PetscErrorCode ierr;
135145471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
135245471136SStefano Zampini   PetscBool      local_sym;
135345471136SStefano Zampini 
135445471136SStefano Zampini   PetscFunctionBegin;
135545471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
135645471136SStefano Zampini     *flg = PETSC_FALSE;
135745471136SStefano Zampini     PetscFunctionReturn(0);
135845471136SStefano Zampini   }
135945471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
136045471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
136145471136SStefano Zampini   PetscFunctionReturn(0);
136245471136SStefano Zampini }
136345471136SStefano Zampini 
136445471136SStefano Zampini #undef __FUNCT__
1365b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
1366a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1367b4319ba4SBarry Smith {
1368dfbe8321SBarry Smith   PetscErrorCode ierr;
1369b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1370b4319ba4SBarry Smith 
1371b4319ba4SBarry Smith   PetscFunctionBegin;
13726bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1373e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1374e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
13756bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
13766bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
13773fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1378a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1379a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1380a8116848SStefano Zampini   if (b->sf != b->csf) {
1381a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1382a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1383a8116848SStefano Zampini   }
138428f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
138528f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1386bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1387dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1388bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1389b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1390b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
13912e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1392cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
1393b4319ba4SBarry Smith   PetscFunctionReturn(0);
1394b4319ba4SBarry Smith }
1395b4319ba4SBarry Smith 
1396b4319ba4SBarry Smith #undef __FUNCT__
1397b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
1398a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1399b4319ba4SBarry Smith {
1400dfbe8321SBarry Smith   PetscErrorCode ierr;
1401b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1402b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1403b4319ba4SBarry Smith 
1404b4319ba4SBarry Smith   PetscFunctionBegin;
1405b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1406e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1407e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1408b4319ba4SBarry Smith 
1409b4319ba4SBarry Smith   /* multiply the local matrix */
1410b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1411b4319ba4SBarry Smith 
1412b4319ba4SBarry Smith   /* scatter product back into global memory */
14132dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1414e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1415e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1416b4319ba4SBarry Smith   PetscFunctionReturn(0);
1417b4319ba4SBarry Smith }
1418b4319ba4SBarry Smith 
1419b4319ba4SBarry Smith #undef __FUNCT__
14202e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
1421a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
14222e74eeadSLisandro Dalcin {
1423650997f4SStefano Zampini   Vec            temp_vec;
14242e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14252e74eeadSLisandro Dalcin 
14262e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1427650997f4SStefano Zampini   if (v3 != v2) {
1428650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1429650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1430650997f4SStefano Zampini   } else {
1431650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1432650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1433650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1434650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1435650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1436650997f4SStefano Zampini   }
14372e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14382e74eeadSLisandro Dalcin }
14392e74eeadSLisandro Dalcin 
14402e74eeadSLisandro Dalcin #undef __FUNCT__
14412e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
1442a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
14432e74eeadSLisandro Dalcin {
14442e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
14452e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14462e74eeadSLisandro Dalcin 
1447e176bc59SStefano Zampini   PetscFunctionBegin;
14482e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1449e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1450e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14512e74eeadSLisandro Dalcin 
14522e74eeadSLisandro Dalcin   /* multiply the local matrix */
1453e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
14542e74eeadSLisandro Dalcin 
14552e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1456e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1457e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1458e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14592e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14602e74eeadSLisandro Dalcin }
14612e74eeadSLisandro Dalcin 
14622e74eeadSLisandro Dalcin #undef __FUNCT__
14632e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
1464a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
14652e74eeadSLisandro Dalcin {
1466650997f4SStefano Zampini   Vec            temp_vec;
14672e74eeadSLisandro Dalcin   PetscErrorCode ierr;
14682e74eeadSLisandro Dalcin 
14692e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1470650997f4SStefano Zampini   if (v3 != v2) {
1471650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1472650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1473650997f4SStefano Zampini   } else {
1474650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1475650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1476650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1477650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1478650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1479650997f4SStefano Zampini   }
14802e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
14812e74eeadSLisandro Dalcin }
14822e74eeadSLisandro Dalcin 
14832e74eeadSLisandro Dalcin #undef __FUNCT__
1484b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
1485a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1486b4319ba4SBarry Smith {
1487b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1488dfbe8321SBarry Smith   PetscErrorCode ierr;
1489b4319ba4SBarry Smith   PetscViewer    sviewer;
1490ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1491b4319ba4SBarry Smith 
1492b4319ba4SBarry Smith   PetscFunctionBegin;
1493ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1494ee2491ecSStefano Zampini   if (isascii)  {
1495ee2491ecSStefano Zampini     PetscViewerFormat format;
1496ee2491ecSStefano Zampini 
1497ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1498ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1499ee2491ecSStefano Zampini   }
1500ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
15013f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1502b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
15033f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
15046e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1505b4319ba4SBarry Smith   PetscFunctionReturn(0);
1506b4319ba4SBarry Smith }
1507b4319ba4SBarry Smith 
1508b4319ba4SBarry Smith #undef __FUNCT__
1509b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
1510a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1511b4319ba4SBarry Smith {
1512dfbe8321SBarry Smith   PetscErrorCode ierr;
1513e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1514b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1515b4319ba4SBarry Smith   IS             from,to;
1516e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1517b4319ba4SBarry Smith 
1518b4319ba4SBarry Smith   PetscFunctionBegin;
1519784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1520e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
15213bbff08aSStefano Zampini   /* Destroy any previous data */
152270cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
152370cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
15243fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1525e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1526e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
15271c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
152828f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
152928f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
15303bbff08aSStefano Zampini 
15313bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1532fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1533fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1534fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
1535fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
1536b4319ba4SBarry Smith 
1537b4319ba4SBarry Smith   /* Create the local matrix A */
1538e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1539e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1540e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1541e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
1542f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1543e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1544e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1545e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1546ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1547ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1548b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1549b4319ba4SBarry Smith 
1550f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1551b4319ba4SBarry Smith     /* Create the local work vectors */
15523bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1553b4319ba4SBarry Smith 
1554e176bc59SStefano Zampini     /* setup the global to local scatters */
1555e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1556e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1557784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1558e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1559e176bc59SStefano Zampini     if (rmapping != cmapping) {
1560e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1561e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1562e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1563e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1564e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1565e176bc59SStefano Zampini     } else {
1566e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1567e176bc59SStefano Zampini       is->cctx = is->rctx;
1568e176bc59SStefano Zampini     }
15693fd1c9e7SStefano Zampini 
15703fd1c9e7SStefano Zampini     /* interface counter vector (local) */
15713fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
15723fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
15733fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15743fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15753fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15763fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15773fd1c9e7SStefano Zampini 
15783fd1c9e7SStefano Zampini     /* free workspace */
1579e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1580e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
15816bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
15826bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1583f26d0771SStefano Zampini   }
15849c0b00dbSStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1585b4319ba4SBarry Smith   PetscFunctionReturn(0);
1586b4319ba4SBarry Smith }
1587b4319ba4SBarry Smith 
15882e74eeadSLisandro Dalcin #undef __FUNCT__
15892e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
1590a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
15912e74eeadSLisandro Dalcin {
15922e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
15932e74eeadSLisandro Dalcin   PetscErrorCode ierr;
159497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
159597563a80SStefano Zampini   PetscInt       i,zm,zn;
159697563a80SStefano Zampini #endif
1597f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
15982e74eeadSLisandro Dalcin 
15992e74eeadSLisandro Dalcin   PetscFunctionBegin;
16002e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1601f26d0771SStefano 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);
160297563a80SStefano Zampini   /* count negative indices */
160397563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
160497563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
16052e74eeadSLisandro Dalcin #endif
160697563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
160797563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
160897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
160997563a80SStefano Zampini   /* count negative indices (should be the same as before) */
161097563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
161197563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
161297563a80SStefano 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");
161397563a80SStefano 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");
161497563a80SStefano Zampini #endif
16152e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
16162e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
16172e74eeadSLisandro Dalcin }
16182e74eeadSLisandro Dalcin 
1619b4319ba4SBarry Smith #undef __FUNCT__
162097563a80SStefano Zampini #define __FUNCT__ "MatSetValuesBlocked_IS"
1621a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
162297563a80SStefano Zampini {
162397563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
162497563a80SStefano Zampini   PetscErrorCode ierr;
162597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
162697563a80SStefano Zampini   PetscInt       i,zm,zn;
162797563a80SStefano Zampini #endif
1628f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
162997563a80SStefano Zampini 
163097563a80SStefano Zampini   PetscFunctionBegin;
163197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
1632f26d0771SStefano 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);
163397563a80SStefano Zampini   /* count negative indices */
163497563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
163597563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
163697563a80SStefano Zampini #endif
163797563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
163897563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
163997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
164097563a80SStefano Zampini   /* count negative indices (should be the same as before) */
164197563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
164297563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
164397563a80SStefano 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");
164497563a80SStefano 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");
164597563a80SStefano Zampini #endif
164697563a80SStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
164797563a80SStefano Zampini   PetscFunctionReturn(0);
164897563a80SStefano Zampini }
164997563a80SStefano Zampini 
165097563a80SStefano Zampini #undef __FUNCT__
1651b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
1652a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1653b4319ba4SBarry Smith {
1654dfbe8321SBarry Smith   PetscErrorCode ierr;
1655b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1656b4319ba4SBarry Smith 
1657b4319ba4SBarry Smith   PetscFunctionBegin;
1658b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1659b4319ba4SBarry Smith   PetscFunctionReturn(0);
1660b4319ba4SBarry Smith }
1661b4319ba4SBarry Smith 
1662b4319ba4SBarry Smith #undef __FUNCT__
1663f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
1664a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1665f0006bf2SLisandro Dalcin {
1666f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
1667f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
1668f0006bf2SLisandro Dalcin 
1669f0006bf2SLisandro Dalcin   PetscFunctionBegin;
1670f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
1671f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
1672f0006bf2SLisandro Dalcin }
1673f0006bf2SLisandro Dalcin 
1674f0006bf2SLisandro Dalcin #undef __FUNCT__
1675f0ae7da4SStefano Zampini #define __FUNCT__ "MatISZeroRowsColumnsLocal_Private"
1676f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
16772e74eeadSLisandro Dalcin {
1678f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
16792e74eeadSLisandro Dalcin   PetscErrorCode ierr;
16802e74eeadSLisandro Dalcin 
16812e74eeadSLisandro Dalcin   PetscFunctionBegin;
1682f0ae7da4SStefano Zampini   if (!n) {
1683f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
1684f0ae7da4SStefano Zampini   } else {
1685f0ae7da4SStefano Zampini     PetscInt i;
1686f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
1687f0ae7da4SStefano Zampini 
1688f0ae7da4SStefano Zampini     if (columns) {
1689f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
1690f0ae7da4SStefano Zampini     } else {
1691f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
16922e74eeadSLisandro Dalcin     }
1693f0ae7da4SStefano Zampini     if (diag != 0.) {
1694f0ae7da4SStefano Zampini       const PetscScalar *array;
1695f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
1696f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
1697f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
1698f0ae7da4SStefano Zampini       }
1699f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
1700f0ae7da4SStefano Zampini     }
1701f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1702f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1703f0ae7da4SStefano Zampini   }
17042e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
17052e74eeadSLisandro Dalcin }
17062e74eeadSLisandro Dalcin 
17072e74eeadSLisandro Dalcin #undef __FUNCT__
1708f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_Private_IS"
1709f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
1710b4319ba4SBarry Smith {
17116e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
17126e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
17136e520ac8SStefano Zampini   PetscInt       *lrows;
1714dfbe8321SBarry Smith   PetscErrorCode ierr;
1715b4319ba4SBarry Smith 
1716b4319ba4SBarry Smith   PetscFunctionBegin;
1717f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
1718f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
1719f0ae7da4SStefano Zampini     PetscBool cong;
1720f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
1721f0ae7da4SStefano 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");
1722f0ae7da4SStefano 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");
1723f0ae7da4SStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent");
1724b4319ba4SBarry Smith   }
1725f0ae7da4SStefano Zampini #endif
17266e520ac8SStefano Zampini   /* get locally owned rows */
1727f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
17286e520ac8SStefano Zampini   /* fix right hand side if needed */
17296e520ac8SStefano Zampini   if (x && b) {
17306e520ac8SStefano Zampini     const PetscScalar *xx;
17316e520ac8SStefano Zampini     PetscScalar       *bb;
17322205254eSKarl Rupp 
17336e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
17346e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
17356e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
17366e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
17376e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
1738b4319ba4SBarry Smith   }
17396e520ac8SStefano Zampini   /* get rows associated to the local matrices */
17403d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
17416e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
17426e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
17436e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
17446e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
17456e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
17466e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17476e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17486e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
17496e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
1750f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
17516e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
1752b4319ba4SBarry Smith   PetscFunctionReturn(0);
1753b4319ba4SBarry Smith }
1754b4319ba4SBarry Smith 
1755b4319ba4SBarry Smith #undef __FUNCT__
1756f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRows_IS"
1757f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1758b4319ba4SBarry Smith {
1759b4319ba4SBarry Smith   PetscErrorCode ierr;
1760b4319ba4SBarry Smith 
1761b4319ba4SBarry Smith   PetscFunctionBegin;
1762f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
1763f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
1764f0ae7da4SStefano Zampini }
1765b4319ba4SBarry Smith 
1766f0ae7da4SStefano Zampini #undef __FUNCT__
1767f0ae7da4SStefano Zampini #define __FUNCT__ "MatZeroRowsColumns_IS"
1768f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1769f0ae7da4SStefano Zampini {
1770f0ae7da4SStefano Zampini   PetscErrorCode ierr;
1771f0ae7da4SStefano Zampini 
1772f0ae7da4SStefano Zampini   PetscFunctionBegin;
1773f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
1774b4319ba4SBarry Smith   PetscFunctionReturn(0);
1775b4319ba4SBarry Smith }
1776b4319ba4SBarry Smith 
1777b4319ba4SBarry Smith #undef __FUNCT__
1778b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
1779a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
1780b4319ba4SBarry Smith {
1781b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1782dfbe8321SBarry Smith   PetscErrorCode ierr;
1783b4319ba4SBarry Smith 
1784b4319ba4SBarry Smith   PetscFunctionBegin;
1785b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
1786b4319ba4SBarry Smith   PetscFunctionReturn(0);
1787b4319ba4SBarry Smith }
1788b4319ba4SBarry Smith 
1789b4319ba4SBarry Smith #undef __FUNCT__
1790b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
1791a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
1792b4319ba4SBarry Smith {
1793b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1794dfbe8321SBarry Smith   PetscErrorCode ierr;
1795b4319ba4SBarry Smith 
1796b4319ba4SBarry Smith   PetscFunctionBegin;
1797b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
1798b4319ba4SBarry Smith   PetscFunctionReturn(0);
1799b4319ba4SBarry Smith }
1800b4319ba4SBarry Smith 
1801b4319ba4SBarry Smith #undef __FUNCT__
1802b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
1803a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
1804b4319ba4SBarry Smith {
1805b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
1806b4319ba4SBarry Smith 
1807b4319ba4SBarry Smith   PetscFunctionBegin;
1808b4319ba4SBarry Smith   *local = is->A;
1809b4319ba4SBarry Smith   PetscFunctionReturn(0);
1810b4319ba4SBarry Smith }
1811b4319ba4SBarry Smith 
1812b4319ba4SBarry Smith #undef __FUNCT__
1813b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
1814b4319ba4SBarry Smith /*@
1815b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
1816b4319ba4SBarry Smith 
1817b4319ba4SBarry Smith   Input Parameter:
1818b4319ba4SBarry Smith .  mat - the matrix
1819b4319ba4SBarry Smith 
1820b4319ba4SBarry Smith   Output Parameter:
1821eb82efa4SStefano Zampini .  local - the local matrix
1822b4319ba4SBarry Smith 
1823b4319ba4SBarry Smith   Level: advanced
1824b4319ba4SBarry Smith 
1825b4319ba4SBarry Smith   Notes:
1826b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
1827b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
1828b4319ba4SBarry Smith   of the MatSetValues() operation.
1829b4319ba4SBarry Smith 
1830b4319ba4SBarry Smith .seealso: MATIS
1831b4319ba4SBarry Smith @*/
18327087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
1833b4319ba4SBarry Smith {
18344ac538c5SBarry Smith   PetscErrorCode ierr;
1835b4319ba4SBarry Smith 
1836b4319ba4SBarry Smith   PetscFunctionBegin;
18370700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1838b4319ba4SBarry Smith   PetscValidPointer(local,2);
18394ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
1840b4319ba4SBarry Smith   PetscFunctionReturn(0);
1841b4319ba4SBarry Smith }
1842b4319ba4SBarry Smith 
18433b03a366Sstefano_zampini #undef __FUNCT__
18443b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
1845a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
18463b03a366Sstefano_zampini {
18473b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
18483b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
18493b03a366Sstefano_zampini   PetscErrorCode ierr;
18503b03a366Sstefano_zampini 
18513b03a366Sstefano_zampini   PetscFunctionBegin;
18524e4c7dbeSStefano Zampini   if (is->A) {
18533b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
18543b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
1855f0ae7da4SStefano 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);
18564e4c7dbeSStefano Zampini   }
18573b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
18583b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
18593b03a366Sstefano_zampini   is->A = local;
18603b03a366Sstefano_zampini   PetscFunctionReturn(0);
18613b03a366Sstefano_zampini }
18623b03a366Sstefano_zampini 
18633b03a366Sstefano_zampini #undef __FUNCT__
18643b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
18653b03a366Sstefano_zampini /*@
1866eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
18673b03a366Sstefano_zampini 
18683b03a366Sstefano_zampini   Input Parameter:
18693b03a366Sstefano_zampini .  mat - the matrix
1870eb82efa4SStefano Zampini .  local - the local matrix
18713b03a366Sstefano_zampini 
18723b03a366Sstefano_zampini   Output Parameter:
18733b03a366Sstefano_zampini 
18743b03a366Sstefano_zampini   Level: advanced
18753b03a366Sstefano_zampini 
18763b03a366Sstefano_zampini   Notes:
18773b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
18783b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
18793b03a366Sstefano_zampini 
18803b03a366Sstefano_zampini .seealso: MATIS
18813b03a366Sstefano_zampini @*/
18823b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
18833b03a366Sstefano_zampini {
18843b03a366Sstefano_zampini   PetscErrorCode ierr;
18853b03a366Sstefano_zampini 
18863b03a366Sstefano_zampini   PetscFunctionBegin;
18873b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1888b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
18893b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
18903b03a366Sstefano_zampini   PetscFunctionReturn(0);
18913b03a366Sstefano_zampini }
18923b03a366Sstefano_zampini 
18936726f965SBarry Smith #undef __FUNCT__
18946726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
1895a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
18966726f965SBarry Smith {
18976726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
18986726f965SBarry Smith   PetscErrorCode ierr;
18996726f965SBarry Smith 
19006726f965SBarry Smith   PetscFunctionBegin;
19016726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
19026726f965SBarry Smith   PetscFunctionReturn(0);
19036726f965SBarry Smith }
19046726f965SBarry Smith 
19056726f965SBarry Smith #undef __FUNCT__
19062e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
1907a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
19082e74eeadSLisandro Dalcin {
19092e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
19102e74eeadSLisandro Dalcin   PetscErrorCode ierr;
19112e74eeadSLisandro Dalcin 
19122e74eeadSLisandro Dalcin   PetscFunctionBegin;
19132e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
19142e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
19152e74eeadSLisandro Dalcin }
19162e74eeadSLisandro Dalcin 
19172e74eeadSLisandro Dalcin #undef __FUNCT__
19182e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
1919a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
19202e74eeadSLisandro Dalcin {
19212e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
19222e74eeadSLisandro Dalcin   PetscErrorCode ierr;
19232e74eeadSLisandro Dalcin 
19242e74eeadSLisandro Dalcin   PetscFunctionBegin;
19252e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
1926e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
19272e74eeadSLisandro Dalcin 
19282e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
19292e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
1930e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1931e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19322e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
19332e74eeadSLisandro Dalcin }
19342e74eeadSLisandro Dalcin 
19352e74eeadSLisandro Dalcin #undef __FUNCT__
19366726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
1937a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
19386726f965SBarry Smith {
19396726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
19406726f965SBarry Smith   PetscErrorCode ierr;
19416726f965SBarry Smith 
19426726f965SBarry Smith   PetscFunctionBegin;
19434e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
19446726f965SBarry Smith   PetscFunctionReturn(0);
19456726f965SBarry Smith }
19466726f965SBarry Smith 
1947284134d9SBarry Smith #undef __FUNCT__
1948f26d0771SStefano Zampini #define __FUNCT__ "MatAXPY_IS"
1949f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
1950f26d0771SStefano Zampini {
1951f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
1952f26d0771SStefano Zampini   Mat_IS         *x;
1953f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1954f26d0771SStefano Zampini   PetscBool      ismatis;
1955f26d0771SStefano Zampini #endif
1956f26d0771SStefano Zampini   PetscErrorCode ierr;
1957f26d0771SStefano Zampini 
1958f26d0771SStefano Zampini   PetscFunctionBegin;
1959f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1960f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
1961f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
1962f26d0771SStefano Zampini #endif
1963f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
1964f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
1965f26d0771SStefano Zampini   PetscFunctionReturn(0);
1966f26d0771SStefano Zampini }
1967f26d0771SStefano Zampini 
1968f26d0771SStefano Zampini #undef __FUNCT__
1969f26d0771SStefano Zampini #define __FUNCT__ "MatGetLocalSubMatrix_IS"
1970f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
1971f26d0771SStefano Zampini {
1972f26d0771SStefano Zampini   Mat                    lA;
1973f26d0771SStefano Zampini   Mat_IS                 *matis;
1974f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
1975f26d0771SStefano Zampini   IS                     is;
1976f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
1977f26d0771SStefano Zampini   PetscInt               nrg;
1978f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
1979f26d0771SStefano Zampini   PetscErrorCode         ierr;
1980f26d0771SStefano Zampini 
1981f26d0771SStefano Zampini   PetscFunctionBegin;
1982f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1983f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
1984f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
1985f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
1986f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1987f0ae7da4SStefano 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);
1988f26d0771SStefano Zampini #endif
1989f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
1990f26d0771SStefano Zampini   /* map from [0,nrl) to row */
1991f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
1992f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1993f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
1994f26d0771SStefano Zampini #else
1995f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
1996f26d0771SStefano Zampini #endif
1997f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
1998f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
1999f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2000f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2001f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
2002f26d0771SStefano Zampini   /* compute new l2g map for columns */
2003f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2004f26d0771SStefano Zampini     const PetscInt *cg,*cl;
2005f26d0771SStefano Zampini     PetscInt       ncg;
2006f26d0771SStefano Zampini     PetscInt       ncl;
2007f26d0771SStefano Zampini 
2008f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2009f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2010f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2011f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2012f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2013f0ae7da4SStefano 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);
2014f26d0771SStefano Zampini #endif
2015f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2016f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2017f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2018f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2019f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2020f26d0771SStefano Zampini #else
2021f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2022f26d0771SStefano Zampini #endif
2023f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2024f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2025f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2026f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2027f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2028f26d0771SStefano Zampini   } else {
2029f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2030f26d0771SStefano Zampini     cl2g = rl2g;
2031f26d0771SStefano Zampini   }
2032f26d0771SStefano Zampini   /* create the MATIS submatrix */
2033f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2034f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2035f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2036f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2037b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2038f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2039f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2040f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2041f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2042f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2043f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2044f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2045f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2046f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2047f26d0771SStefano Zampini   /* remove unsupported ops */
2048f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2049f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2050f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2051f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2052f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2053f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2054f26d0771SStefano Zampini   PetscFunctionReturn(0);
2055f26d0771SStefano Zampini }
2056f26d0771SStefano Zampini 
2057f26d0771SStefano Zampini #undef __FUNCT__
2058284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
2059284134d9SBarry Smith /*@
20603c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2061284134d9SBarry Smith        process but not across processes.
2062284134d9SBarry Smith 
2063284134d9SBarry Smith    Input Parameters:
2064284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2065e176bc59SStefano Zampini .     bs      - block size of the matrix
2066df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2067e176bc59SStefano Zampini .     rmap    - local to global map for rows
2068e176bc59SStefano Zampini -     cmap    - local to global map for cols
2069284134d9SBarry Smith 
2070284134d9SBarry Smith    Output Parameter:
2071284134d9SBarry Smith .    A - the resulting matrix
2072284134d9SBarry Smith 
20738e6c10adSSatish Balay    Level: advanced
20748e6c10adSSatish Balay 
20753c212e90SHong Zhang    Notes: See MATIS for more details.
20766fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
20776fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
20783c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2079284134d9SBarry Smith 
2080284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2081284134d9SBarry Smith @*/
2082e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2083284134d9SBarry Smith {
2084284134d9SBarry Smith   PetscErrorCode ierr;
2085284134d9SBarry Smith 
2086284134d9SBarry Smith   PetscFunctionBegin;
20876fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2088284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
20896fdf41d1SStefano Zampini   if (bs > 0) {
2090d3ee2243SStefano Zampini     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
20916fdf41d1SStefano Zampini   }
2092284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
2093284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2094e176bc59SStefano Zampini   if (rmap && cmap) {
2095e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2096e176bc59SStefano Zampini   } else if (!rmap) {
2097e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2098e176bc59SStefano Zampini   } else {
2099e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2100e176bc59SStefano Zampini   }
2101284134d9SBarry Smith   PetscFunctionReturn(0);
2102284134d9SBarry Smith }
2103284134d9SBarry Smith 
2104b4319ba4SBarry Smith /*MC
2105f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2106b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2107b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2108b4319ba4SBarry Smith    product is handled "implicitly".
2109b4319ba4SBarry Smith 
2110b4319ba4SBarry Smith    Operations Provided:
21116726f965SBarry Smith +  MatMult()
21122e74eeadSLisandro Dalcin .  MatMultAdd()
21132e74eeadSLisandro Dalcin .  MatMultTranspose()
21142e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
21156726f965SBarry Smith .  MatZeroEntries()
21166726f965SBarry Smith .  MatSetOption()
21172e74eeadSLisandro Dalcin .  MatZeroRows()
21182e74eeadSLisandro Dalcin .  MatSetValues()
211997563a80SStefano Zampini .  MatSetValuesBlocked()
21206726f965SBarry Smith .  MatSetValuesLocal()
212197563a80SStefano Zampini .  MatSetValuesBlockedLocal()
21222e74eeadSLisandro Dalcin .  MatScale()
21232e74eeadSLisandro Dalcin .  MatGetDiagonal()
21242b404112SStefano Zampini .  MatMissingDiagonal()
21252b404112SStefano Zampini .  MatDuplicate()
21262b404112SStefano Zampini .  MatCopy()
2127f26d0771SStefano Zampini .  MatAXPY()
2128f26d0771SStefano Zampini .  MatGetSubMatrix()
2129f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2130d7f69cd0SStefano Zampini .  MatTranspose()
21316726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2132b4319ba4SBarry Smith 
2133b4319ba4SBarry Smith    Options Database Keys:
2134b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
2135b4319ba4SBarry Smith 
2136b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
2137b4319ba4SBarry Smith 
2138b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2139b4319ba4SBarry Smith 
2140b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2141eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2142b4319ba4SBarry Smith 
2143b4319ba4SBarry Smith   Level: advanced
2144b4319ba4SBarry Smith 
2145f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2146b4319ba4SBarry Smith 
2147b4319ba4SBarry Smith M*/
2148b4319ba4SBarry Smith 
2149b4319ba4SBarry Smith #undef __FUNCT__
2150b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
21518cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2152b4319ba4SBarry Smith {
2153dfbe8321SBarry Smith   PetscErrorCode ierr;
2154b4319ba4SBarry Smith   Mat_IS         *b;
2155b4319ba4SBarry Smith 
2156b4319ba4SBarry Smith   PetscFunctionBegin;
2157b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2158b4319ba4SBarry Smith   A->data = (void*)b;
2159b4319ba4SBarry Smith 
2160e176bc59SStefano Zampini   /* matrix ops */
2161e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2162b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
21632e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
21642e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
21652e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2166b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2167b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
21682e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
216998921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2170b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2171f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
21722e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2173f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2174b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2175b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2176b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
21776726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
21782e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
21792e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
21806726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
218169796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
218269796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
218345471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2184ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
21856bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
21862b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2187659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
2188a8116848SStefano Zampini   A->ops->getsubmatrix            = MatGetSubMatrix_IS;
2189f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
21903fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
21913fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2192d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
2193b4319ba4SBarry Smith 
2194b7ce53b6SStefano Zampini   /* special MATIS functions */
2195bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
2196bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2197b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
21982e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2199cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
220017667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2201b4319ba4SBarry Smith   PetscFunctionReturn(0);
2202b4319ba4SBarry Smith }
2203